add "uk" to the list of languages. remove the alternate attribute bit --
authorNalin Dahyabhai <nalin@src.gnome.org>
Tue, 10 Dec 2002 00:08:32 +0000 (00:08 +0000)
committerNalin Dahyabhai <nalin@src.gnome.org>
Tue, 10 Dec 2002 00:08:32 +0000 (00:08 +0000)
* configure.in: add "uk" to the list of languages.
* src/vte.h: remove the alternate attribute bit -- it's no longer meaningful.
* python/vte.override: remove the alternate attribute, add the strikethrough
attribute.
* src/vte.c (vte_terminal_insert_char): perform drawing character set to
Unicode mapping at insertion time if the alternate attribute is set,
otherwise discarding the attribute.  If the character being inserted is
a graphic character, force its width to 1 or 2 depending on the current
codeset (#99603).
* src/vte.c (xlfd_from_pango_font_description): take advantage of XftXlfdParse
if we were built with Xft, as it appears to handle family aliases.
* src/vte.c (vte_terminal_draw_graphic): decide what to draw using Unicode code
points (instead of reverse mappings to drawing set), and implement the
double-thick versions of many of the existing glyphs.  Return a boolean
indicating whether or not we drew something.
* src/vte.c (vte_terminal_draw_row): if vte_terminal_draw_graphic() returns
FALSE, try to draw the graphic character using the current font.
* src/vte.c (vte_terminal_paint): if vte_terminal_draw_graphic() returns FALSE,
try to draw the graphic character using the current font.
* src/caps.c: add the undocumented default 0 to the OSC set text parameters
sequence (#100468).
* README: updates.
* src/iso2022.c, src/iso2022.h: add a width mask for overriding widths for
ambiguous Unicode characters, and _vte_iso2022_get_width() for reading
the width, using unused bits in Unicode in a manner similar to
http://www.cl.cam.ac.uk/~mgk25/ucs/iso2022-wc.html
* src/table.c,src/trie.c: strip out iso2022 widths when extracting parameters
of control sequences.
* src/vte.c: heed iso2022 widths when inserting characters into the screen
buffer, but clear then before storing them so that copy and paste will
continue to work.
* src/matcher.c, src/matcher.h: add matcher, a wrapper for table and trie, and
move _vte_table_narrow_encoding and _vte_table_wide_encoding to this
module.

17 files changed:
ChangeLog
README
configure.in
python/vte.override
src/Makefile.am
src/caps.c
src/interpret.c
src/iso2022.c
src/iso2022.h
src/table.c
src/table.h
src/trie.c
src/trie.h
src/utf8echo.c
src/vte.c
src/vte.h
vte.spec

index 1fa2e56..0bebd6c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2002-12-09  nalin
+       * configure.in: add "uk" to the list of languages.
+       * src/vte.h: remove the alternate attribute bit -- it's no longer
+       meaningful.
+       * python/vte.override: remove the alternate attribute, add the
+       strikethrough attribute.
+       * src/vte.c (vte_terminal_insert_char): perform drawing character set
+       to Unicode mapping at insertion time if the alternate attribute is set,
+       otherwise discarding the attribute.  If the character being inserted is
+       a graphic character, force its width to 1 or 2 depending on the current
+       codeset (#99603).
+       * src/vte.c (xlfd_from_pango_font_description): take advantage of
+       XftXlfdParse if we were built with Xft, as it appears to handle family
+       aliases.
+       * src/vte.c (vte_terminal_draw_graphic): decide what to draw using
+       Unicode code points (instead of reverse mappings to drawing set), and
+       implement the double-thick versions of many of the existing glyphs.
+       Return a boolean indicating whether or not we drew something.
+       * src/vte.c (vte_terminal_draw_row): if vte_terminal_draw_graphic()
+       returns FALSE, try to draw the graphic character using the current font.
+       * src/vte.c (vte_terminal_paint): if vte_terminal_draw_graphic()
+       returns FALSE, try to draw the graphic character using the current font.
+       * src/caps.c: add the undocumented default 0 to the OSC set text
+       parameters sequence (#100468).
+
+2002-12-03  nalin
+       * README: updates.
+       * src/iso2022.c, src/iso2022.h: add a width mask for overriding widths
+       for ambiguous Unicode characters, and _vte_iso2022_get_width() for
+       reading the width, using unused bits in Unicode in a manner similar to
+       http://www.cl.cam.ac.uk/~mgk25/ucs/iso2022-wc.html
+       * src/table.c,src/trie.c: strip out iso2022 widths when extracting
+       parameters of control sequences.
+       * src/vte.c: heed iso2022 widths when inserting characters into the
+       screen buffer, but clear then before storing them so that copy and
+       paste will continue to work.
+       * src/matcher.c, src/matcher.h: add matcher, a wrapper for table and
+       trie, and move _vte_table_narrow_encoding and _vte_table_wide_encoding
+       to this module.
+
 2002-12-03  nalin
        * src/pty.c: if TIOCSCTTY is defined, use it, even if it's redundant.
 
diff --git a/README b/README
index 2dc05d4..f1c8b68 100644 (file)
--- a/README
+++ b/README
@@ -20,7 +20,6 @@
 
 * What's missing?
 - Accessibility doesn't work right yet.
-- The keymapping doesn't mimic XTerm as well as it's meant to.
 - Chinese and Korean text isn't displayed correctly because we pass it through
   iconv() before performing substitutions, and they both use GR characters.
   Japanese works because it only uses GL characters, which iconv() essentially
@@ -58,3 +57,5 @@
   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
+- Depending on your locale, the current encoding, and possibly the strengh
+  of cosmic rays, the display width of certain Unicode characters changes.
index 6c86cb8..cd19c67 100644 (file)
@@ -9,7 +9,7 @@ AM_PROG_CC_STDC
 AM_MAINTAINER_MODE
 
 AM_PROG_LIBTOOL
-ALL_LINGUAS="cs da de fr ms nl no pt_BR sv vi"
+ALL_LINGUAS="cs da de fr ms nl no pt_BR sv uk vi"
 AM_GLIB_GNU_GETTEXT
 AC_EGREP_CPP(glibc,
                [
index 849bd8c..86fc12a 100644 (file)
@@ -197,8 +197,8 @@ _wrap_vte_terminal_get_text(PyGObject *self, PyObject *args, PyObject *kwargs)
            
            PyDict_SetItemString(py_char_attr, "underline", 
                    PyInt_FromLong(cht->underline));
-           PyDict_SetItemString(py_char_attr, "alternate", 
-                   PyInt_FromLong(cht->alternate));
+           PyDict_SetItemString(py_char_attr, "strikethrough", 
+                   PyInt_FromLong(cht->strikethrough));
 
            PyTuple_SetItem(py_attrs, count, py_char_attr);
        }
@@ -292,8 +292,8 @@ _wrap_vte_terminal_get_text_range(PyGObject *self, PyObject *args, PyObject *kwa
            
            PyDict_SetItemString(py_char_attr, "underline", 
                    PyInt_FromLong(cht->underline));
-           PyDict_SetItemString(py_char_attr, "alternate", 
-                   PyInt_FromLong(cht->alternate));
+           PyDict_SetItemString(py_char_attr, "strikethrough", 
+                   PyInt_FromLong(cht->strikethrough));
 
            PyTuple_SetItem(py_attrs, count, py_char_attr);
        }
index ac57067..99ede62 100644 (file)
@@ -33,6 +33,8 @@ libvte_la_SOURCES = \
        keymap.h \
        marshal.c \
        marshal.h \
+       matcher.c \
+       matcher.h \
        pty.c \
        pty.h \
        reaper.c \
@@ -73,8 +75,12 @@ interpret_SOURCES = \
        debug.h \
        iso2022.c \
        iso2022.h \
+       matcher.c \
+       matcher.h \
        table.c \
        table.h \
+       trie.c \
+       trie.h \
        termcap.c \
        termcap.h \
        interpret.c
@@ -86,16 +92,24 @@ iso2022_SOURCES = \
        debug.h \
        iso2022.c \
        iso2022.h \
+       matcher.c \
+       matcher.h \
        table.c \
-       table.h
+       table.h \
+       trie.c \
+       trie.h
 iso2022_LDADD = @LIBS@ @GOBJECT_LIBS@
 
 utf8echo_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DUTF8ECHO_MAIN
 utf8echo_SOURCES = \
        debug.c \
        debug.h \
+       matcher.c \
+       matcher.h \
        table.c \
        table.h \
+       trie.c \
+       trie.h \
        utf8echo.c
 utf8echo_LDADD = @LIBS@ @GOBJECT_LIBS@
 
@@ -120,14 +134,20 @@ table_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTABLE_MAIN
 table_SOURCES = \
        debug.c \
        debug.h \
+       matcher.c \
+       matcher.h \
        table.c \
-       table.h
+       table.h \
+       trie.c \
+       trie.h
 table_LDADD = @LIBS@ @GOBJECT_LIBS@
 
 trie_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTRIE_MAIN
 trie_SOURCES = \
        debug.c \
        debug.h \
+       matcher.c \
+       matcher.h \
        table.c \
        table.h \
        termcap.c \
index 0e0c394..894b22b 100644 (file)
@@ -513,6 +513,7 @@ struct _vte_capability_string _vte_xterm_capability_strings[] = {
        {CSI "%m'{", "select-locator-events", 0},
        {CSI "%d'|", "request-locator-position", 0},
 
+       {OSC ";%s" BEL, "set-icon-and-window-title", 0}, /* undocumented default */
        {OSC "0;%s" BEL, "set-icon-and-window-title", 0},
        {OSC "1;%s" BEL, "set-icon-title", 0},
        {OSC "2;%s" BEL, "set-window-title", 0},
index 54b2418..acddc34 100644 (file)
 #include "caps.h"
 #include "debug.h"
 #include "iso2022.h"
+#include "matcher.h"
 #include "termcap.h"
-#include "table.h"
 
 int
 main(int argc, char **argv)
 {
        char *terminal = NULL;
-       struct _vte_table *table = NULL;
+       struct _vte_matcher *matcher = NULL;
        struct _vte_termcap *termcap = NULL;
        GByteArray *array = NULL;
        int i, j;
@@ -75,7 +75,7 @@ main(int argc, char **argv)
 
        g_type_init();
        terminal = argv[1];
-       table = _vte_table_new();
+       matcher = _vte_matcher_new(terminal);
        termcap = _vte_termcap_new(g_strdup_printf(DATADIR "/" PACKAGE
                                                   "/termcap/%s", terminal));
        if (termcap == NULL) {
@@ -94,7 +94,7 @@ main(int argc, char **argv)
                }
                tmp = _vte_termcap_find_string(termcap, terminal, capability);
                if ((tmp != NULL) && (strlen(tmp) > 0)) {
-                       _vte_table_add(table, tmp, strlen(tmp), capability,
+                       _vte_matcher_add(matcher, tmp, strlen(tmp), capability,
                                       g_quark_from_static_string(capability));
                }
                g_free(tmp);
@@ -103,8 +103,8 @@ main(int argc, char **argv)
                const char *code, *value;
                code = _vte_xterm_capability_strings[i].code;
                value = _vte_xterm_capability_strings[i].value;
-               _vte_table_add(table, code, strlen(code), value,
-                              g_quark_from_static_string(code));
+               _vte_matcher_add(matcher, code, strlen(code), value,
+                                g_quark_from_static_string(code));
        }
 
        substitutions = _vte_iso2022_new();
@@ -114,7 +114,7 @@ main(int argc, char **argv)
                for (i = 1; i <= array->len; i++) {
                        ubuf = (gunichar*) g_convert((const gchar*)array->data,
                                                     i,
-                                                    _vte_table_wide_encoding(),
+                                                    _vte_matcher_wide_encoding(),
                                                     "UTF-8",
                                                     NULL, &ubuflen, &error);
                        if (error != NULL) {
@@ -147,7 +147,7 @@ main(int argc, char **argv)
                                                           ubuf,
                                                           ubuflen / sizeof(gunichar),
                                                           ubuf,
-                                                          table);
+                                                          matcher);
                        if (substlen < 0) {
                                /* Incomplete state-change. */
                                _vte_iso2022_free(tmpsubst);
@@ -167,8 +167,8 @@ main(int argc, char **argv)
                                break;
                        }
 
-                       _vte_table_match(table, ubuf, substlen,
-                                        &tmp, NULL, &quark, &values);
+                       _vte_matcher_match(matcher, ubuf, substlen,
+                                          &tmp, NULL, &quark, &values);
                        if (tmp != NULL) {
                                if (strlen(tmp) > 0) {
                                        printf("%s(", g_quark_to_string(quark));
@@ -229,6 +229,6 @@ main(int argc, char **argv)
        _vte_iso2022_free(substitutions);
        g_byte_array_free(array, TRUE);
        _vte_termcap_free(termcap);
-       _vte_table_free(table);
+       _vte_matcher_free(matcher);
        return 0;
 }
index 2e93d87..597d0f1 100644 (file)
@@ -44,7 +44,7 @@ struct _vte_iso2022_map {
 
 struct _vte_iso2022 {
        unsigned int current, override;
-       gboolean ss2, ss3;
+       gboolean ss0, ss1, ss2, ss3;
        gunichar g[4];
 };
 
@@ -256,6 +256,8 @@ _vte_iso2022_new(void)
        ret = g_malloc0(sizeof(struct _vte_iso2022));
        ret->current = 0;
        ret->override = 0;
+       ret->ss0 = FALSE;
+       ret->ss1 = FALSE;
        ret->ss2 = FALSE;
        ret->ss3 = FALSE;
        ret->g[0] = 'B';
@@ -429,10 +431,27 @@ _vte_iso2022_map_get(gunichar mapname)
        return ret;
 }
 
+gssize
+_vte_iso2022_get_width(gunichar c)
+{
+       gssize width;
+       width = (c & VTE_ISO2022_WIDTH_MASK) >> VTE_ISO2022_WIDTH_BIT_OFFSET;
+       return CLAMP(width, 0, 2);
+}
+
+static gunichar
+_vte_iso2022_set_width(gunichar c, gssize width)
+{
+       width = CLAMP(width, 0, 2);
+       c &= ~(VTE_ISO2022_WIDTH_MASK);
+       c |= (width << VTE_ISO2022_WIDTH_BIT_OFFSET);
+       return c;
+}
+
 gssize
 _vte_iso2022_substitute(struct _vte_iso2022 *outside_state,
                       gunichar *instring, gssize length,
-                      gunichar *outstring, struct _vte_table *specials)
+                      gunichar *outstring, struct _vte_matcher *specials)
 {
        int i, j, k, g;
        struct _vte_iso2022 state;
@@ -443,6 +462,7 @@ _vte_iso2022_substitute(struct _vte_iso2022 *outside_state,
        const char *match;
        const gunichar *used;
        int chars_per_code = 1;
+       gssize width;
 
        g_return_val_if_fail(outside_state != NULL, 0);
        g_return_val_if_fail(instring != NULL, 0);
@@ -454,8 +474,8 @@ _vte_iso2022_substitute(struct _vte_iso2022 *outside_state,
 
        for (i = j = 0; i < length; i++) {
                if ((specials != NULL) &&
-                   (_vte_table_match(specials, instring + i, length - i,
-                                     &match, &used, NULL, NULL) != NULL)) {
+                   (_vte_matcher_match(specials, instring + i, length - i,
+                                       &match, &used, NULL, NULL) != NULL)) {
                        if (strlen(match) > 0) {
                                /* Aaargh, SI/SO masquerade as capabilities. */
                                if ((strcmp(match, "as") != 0) &&
@@ -721,6 +741,14 @@ _vte_iso2022_substitute(struct _vte_iso2022 *outside_state,
                        if (state.ss3) {
                                current_map = state.g[3];
                                state.ss3 = FALSE;
+                       } else
+                       if (state.ss0) {
+                               current_map = state.g[0];
+                               state.ss0 = FALSE;
+                       } else
+                       if (state.ss1) {
+                               current_map = state.g[1];
+                               state.ss1 = FALSE;
                        } else {
                                g_assert(state.current < G_N_ELEMENTS(state.g));
                                current_map = state.g[state.current];
@@ -805,6 +833,18 @@ _vte_iso2022_substitute(struct _vte_iso2022 *outside_state,
 #endif
                                }
                        }
+                       /* Calculate width for ambiguous characters. */
+                       switch (result) {
+                               /* To be filled in some time, I guess. */
+                       default:
+                               /* For nonambiguous characters, just use
+                                * the width glib has later on. */
+                               width = 0;
+                               break;
+                       }
+                       if (width != 0) {
+                               result = _vte_iso2022_set_width(result, width);
+                       }
                        /* Store. */
                        buf[j++] = result;
                        accumulator = 0;
index a7c152d..012201a 100644 (file)
@@ -25,7 +25,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
-#include "table.h"
+#include "matcher.h"
 
 G_BEGIN_DECLS
 
@@ -35,7 +35,12 @@ void _vte_iso2022_free(struct _vte_iso2022 *p);
 gssize _vte_iso2022_substitute(struct _vte_iso2022 *state,
                               gunichar *instring, gssize length,
                               gunichar *outstring,
-                              struct _vte_table *specials);
+                              struct _vte_matcher *specials);
+
+#define VTE_ISO2022_WIDTH_BIT_OFFSET   28
+#define VTE_ISO2022_WIDTH_MASK         (3 << VTE_ISO2022_WIDTH_BIT_OFFSET)
+#define VTE_ISO2022_HAS_WIDTH(__c)     (((__c) & VTE_ISO2022_WIDTH_MASK) != 0)
+gssize _vte_iso2022_get_width(gunichar c);
 
 G_END_DECLS
 
index f5f6467..a470ee2 100644 (file)
@@ -27,6 +27,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include "debug.h"
+#include "iso2022.h"
 #include "table.h"
 
 #ifdef ENABLE_NLS
@@ -405,9 +406,13 @@ _vte_table_extract_string(GValueArray **array,
 {
        GValue value = {0,};
        gunichar *ptr;
+       int i;
 
        ptr = g_malloc(sizeof(gunichar) * (arginfo->length + 1));
        memcpy(ptr, arginfo->start, (arginfo->length * sizeof(gunichar)));
+       for (i = 0; i < arginfo->length; i++) {
+               ptr[i] &= ~(VTE_ISO2022_WIDTH_MASK);
+       }
        ptr[arginfo->length] = '\0';
        g_value_init(&value, G_TYPE_POINTER);
        g_value_set_pointer(&value, ptr);
@@ -639,124 +644,6 @@ _vte_table_print(struct _vte_table *table)
                count, (long) count * sizeof(struct _vte_table));
 }
 
-/* Determine sensible iconv target names for gunichar and iso-8859-1. */
-#define SAMPLE "ABCDEF"
-static char *
-_vte_table_find_valid_encoding(char **list, gssize 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;
-}
-
-const char *
-_vte_table_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_table_find_valid_encoding(wide,
-                                                    G_N_ELEMENTS(wide),
-                                                    TRUE);
-       }
-       return ret;
-}
-
-const char *
-_vte_table_narrow_encoding()
-{
-       char *narrow[] = {
-               "8859-1",
-               "ISO-8859-1",
-               "ISO8859-1",
-       };
-       static char *ret = NULL;
-       if (ret == NULL) {
-               ret = _vte_table_find_valid_encoding(narrow,
-                                                    G_N_ELEMENTS(narrow),
-                                                    FALSE);
-       }
-       return ret;
-}
-
 #ifdef TABLE_MAIN
 /* Return an escaped version of a string suitable for printing. */
 static char *
index f157e10..d69dbd6 100644 (file)
@@ -29,6 +29,8 @@ struct _vte_table;
 
 /* Create an empty, one-level table. */
 struct _vte_table *_vte_table_new(void);
+
+/* Free a table tree. */
 void _vte_table_free(struct _vte_table *table);
 
 /* Add a string to the matching tree. */
@@ -44,10 +46,4 @@ const char *_vte_table_match(struct _vte_table *table,
 /* Dump out the contents of a tree. */
 void _vte_table_print(struct _vte_table *table);
 
-/* A gunichar-compatible giconv target, if one can be found. */
-const char *_vte_table_wide_encoding(void);
-
-/* A single-byte iso-8859-1 giconv target, if one can be found. */
-const char *_vte_table_narrow_encoding(void);
-
 #endif
index 040c7ee..23fbdf2 100644 (file)
@@ -30,7 +30,8 @@
 #include <glib.h>
 #include <glib-object.h>
 #include "debug.h"
-#include "table.h"
+#include "iso2022.h"
+#include "matcher.h"
 #include "trie.h"
 
 #ifndef HAVE_WINT_T
@@ -303,11 +304,15 @@ char_class_string_extract(const gunichar *s, size_t length,
 {
        gunichar *ret = NULL;
        size_t len;
+       int i;
        GValue value;
 
        len = unichar_snlen(s, length);
        ret = g_malloc0((len + 1) * sizeof(gunichar));
        unichar_sncpy(ret, s, len);
+       for (i = 0; i < len; i++) {
+               ret[i] &= ~(VTE_ISO2022_WIDTH_MASK);
+       }
 #ifdef VTE_DEBUG
        if (_vte_debug_on(VTE_DEBUG_PARSE)) {
                fprintf(stderr, "Extracting string `%ls'.\n", (wchar_t*) ret);
@@ -495,7 +500,7 @@ _vte_trie_add(struct _vte_trie *trie, const char *pattern, size_t length,
        wlength = sizeof(gunichar) * (length + 1);
        wpattern = wpattern_end = g_malloc0(wlength + 1);
 
-       conv = g_iconv_open(_vte_trie_wide_encoding(), "UTF-8");
+       conv = g_iconv_open(_vte_matcher_wide_encoding(), "UTF-8");
        g_assert(conv != ((GIConv) -1));
 
        tpattern = (char*)pattern;
@@ -702,9 +707,15 @@ _vte_trie_match(struct _vte_trie *trie, const gunichar *pattern, size_t length,
                        }
                        g_value_array_free(valuearray);
                }
-               *array = NULL;
+               if (array != NULL) {
+                       *array = NULL;
+               }
        } else {
-               *array = valuearray;
+               if (array != NULL) {
+                       *array = valuearray;
+               } else {
+                       g_value_array_free(valuearray);
+               }
        }
 
        return ret;
@@ -796,18 +807,6 @@ _vte_trie_print(struct _vte_trie *trie)
        printf("Trie has %ld nodes.\n", (long) nodecount);
 }
 
-TRIE_MAYBE_STATIC const char *
-_vte_trie_wide_encoding()
-{
-       return _vte_table_wide_encoding();
-}
-
-TRIE_MAYBE_STATIC const char *
-_vte_trie_narrow_encoding()
-{
-       return _vte_table_narrow_encoding();
-}
-
 #ifdef TRIE_MAIN
 static void
 dump_array(GValueArray *array)
@@ -842,7 +841,7 @@ convert_mbstowcs(const char *i, size_t ilen,
 {
        GIConv conv;
        size_t outlen;
-       conv = g_iconv_open(_vte_trie_wide_encoding(), "UTF-8");
+       conv = g_iconv_open(_vte_matcher_wide_encoding(), "UTF-8");
        g_assert(conv != ((GIConv) -1));
 
        memset(o, 0, max_olen);
@@ -891,8 +890,8 @@ main(int argc, char **argv)
        _vte_trie_add(trie, "<esc>]2;%sh", 11, "decset-title",
                      g_quark_from_string("decset-title"));
 
-       printf("Wide encoding is `%s'.\n", _vte_trie_wide_encoding());
-       printf("Narrow encoding is `%s'.\n", _vte_trie_narrow_encoding());
+       printf("Wide encoding is `%s'.\n", _vte_matcher_wide_encoding());
+       printf("Narrow encoding is `%s'.\n", _vte_matcher_narrow_encoding());
 
        _vte_trie_print(trie);
        printf("\n");
index 8672568..771c288 100644 (file)
@@ -59,12 +59,6 @@ const char *_vte_trie_match(struct _vte_trie *trie,
 /* Print the contents of the trie (mainly for diagnostic purposes). */
 void _vte_trie_print(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
index f999198..cefb596 100644 (file)
@@ -24,7 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include "table.h"
+#include "matcher.h"
 #define ESC "\e"
 
 int
@@ -45,7 +45,7 @@ main(int argc, char **argv)
                return 1;
        }
 
-       conv = g_iconv_open("UTF-8", _vte_table_wide_encoding());
+       conv = g_iconv_open("UTF-8", _vte_matcher_wide_encoding());
        if (conv == ((GIConv) -1)) {
                return 1;
        }
index 00a9a35..38a82fc 100644 (file)
--- a/src/vte.c
+++ b/src/vte.c
 #include "iso2022.h"
 #include "keymap.h"
 #include "marshal.h"
+#include "matcher.h"
 #include "pty.h"
 #include "reaper.h"
 #include "ring.h"
 #include "termcap.h"
-#include "table.h"
 #include "vte.h"
 #include "vteaccess.h"
 #include <X11/Xlib.h>
@@ -171,7 +171,7 @@ typedef struct _VteWordCharRange {
 struct _VteTerminalPrivate {
        /* Emulation setup data. */
        struct _vte_termcap *termcap;   /* termcap storage */
-       struct _vte_table *table;               /* control sequence table */
+       struct _vte_matcher *matcher;   /* control sequence matcher */
        const char *termcap_path;       /* path to termcap file */
        const char *emulation;          /* terminal type to emulate */
        GTree *sequences;               /* sequence handlers, keyed by GQuark
@@ -205,6 +205,7 @@ struct _VteTerminalPrivate {
 
        /* Input data queues. */
        const char *encoding;           /* the pty's encoding */
+       GQuark encodingq;               /* the pty's encoding */
        struct _vte_iso2022 *substitutions;
        GIConv incoming_conv;           /* narrow/unichar conversion state */
        struct _vte_buffer *incoming;   /* pending output characters */
@@ -397,6 +398,7 @@ static void vte_terminal_setup_background(VteTerminal *terminal,
                                          gboolean refresh_transparent);
 static void vte_terminal_ensure_cursor(VteTerminal *terminal, gboolean current);
 static void vte_terminal_paste(VteTerminal *terminal, GdkAtom board);
+static gboolean vte_unichar_isgraphic(gunichar c);
 static void vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
                                     gboolean force_insert_mode,
                                     gboolean invalidate_cells,
@@ -1839,19 +1841,19 @@ vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset)
        }
 
        /* Open new conversions. */
-       new_iconv = g_iconv_open(_vte_table_wide_encoding(), codeset);
+       new_iconv = g_iconv_open(_vte_matcher_wide_encoding(), codeset);
        if (new_iconv == ((GIConv) -1)) {
                g_warning(_("Unable to convert characters from %s to %s."),
-                         codeset, _vte_table_wide_encoding());
+                         codeset, _vte_matcher_wide_encoding());
                if (terminal->pvt->encoding != NULL) {
                        /* Keep the current encoding. */
                        return;
                }
        }
-       new_oconvw = g_iconv_open(codeset, _vte_table_wide_encoding());
+       new_oconvw = g_iconv_open(codeset, _vte_matcher_wide_encoding());
        if (new_oconvw == ((GIConv) -1)) {
                g_warning(_("Unable to convert characters from %s to %s."),
-                         _vte_table_wide_encoding(), codeset);
+                         _vte_matcher_wide_encoding(), codeset);
                if (new_iconv != ((GIConv) -1)) {
                        g_iconv_close(new_iconv);
                }
@@ -1877,16 +1879,17 @@ vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset)
        }
 
        if (new_oconvu == ((GIConv) -1)) {
-               codeset = _vte_table_narrow_encoding();
-               new_iconv = g_iconv_open(_vte_table_wide_encoding(), codeset);
+               codeset = _vte_matcher_narrow_encoding();
+               new_iconv = g_iconv_open(_vte_matcher_wide_encoding(), codeset);
                if (new_iconv == ((GIConv) -1)) {
                        g_error(_("Unable to convert characters from %s to %s."),
-                               codeset, _vte_table_wide_encoding());
+                               codeset, _vte_matcher_wide_encoding());
                }
-               new_oconvw = g_iconv_open(codeset, _vte_table_wide_encoding());
+               new_oconvw = g_iconv_open(codeset,
+                                         _vte_matcher_wide_encoding());
                if (new_oconvw == ((GIConv) -1)) {
                        g_error(_("Unable to convert characters from %s to %s."),
-                               _vte_table_wide_encoding(), codeset);
+                               _vte_matcher_wide_encoding(), codeset);
                }
                new_oconvu = g_iconv_open(codeset, "UTF-8");
                if (new_oconvu == ((GIConv) -1)) {
@@ -1915,6 +1918,7 @@ vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset)
        /* Set the terminal's encoding to the new value. */
        encoding_quark = g_quark_from_string(codeset);
        terminal->pvt->encoding = g_quark_to_string(encoding_quark);
+       terminal->pvt->encodingq = encoding_quark;
 
        /* Convert any buffered output bytes. */
        if ((_vte_buffer_length(terminal->pvt->outgoing) > 0) &&
@@ -3921,7 +3925,8 @@ vte_sequence_handler_set_title_internal(VteTerminal *terminal,
                if (G_VALUE_HOLDS_POINTER(value)) {
                        /* Convert the unicode-character string into a
                         * multibyte string. */
-                       conv = g_iconv_open("UTF-8", _vte_table_wide_encoding());
+                       conv = g_iconv_open("UTF-8",
+                                           _vte_matcher_wide_encoding());
                        inbuf = g_value_get_pointer(value);
                        inbuf_len = vte_unicode_strlen((gunichar*)inbuf) *
                                    sizeof(gunichar);
@@ -4814,7 +4819,7 @@ vte_sequence_handler_local_charset(VteTerminal *terminal,
 {
        G_CONST_RETURN char *locale_encoding;
 #ifdef VTE_DEFAULT_ISO_8859_1
-       vte_terminal_set_encoding(terminal, _vte_table_narrow_encoding());
+       vte_terminal_set_encoding(terminal, _vte_matcher_narrow_encoding());
 #else
        g_get_charset(&locale_encoding);
        vte_terminal_set_encoding(terminal, locale_encoding);
@@ -6081,6 +6086,29 @@ vte_terminal_set_default_colors(VteTerminal *terminal)
        vte_terminal_set_colors(terminal, NULL, NULL, NULL, 0);
 }
 
+/* A list of codeset names in which we consider ambiguous characters to be
+ * wide. */
+static const char *vte_ambiguous_wide_codeset_list[] = {
+       "eucCN",
+       "eucJP",
+       "eucKR",
+       "eucTW",
+       "euc-CN",
+       "euc-JP",
+       "euc-KR",
+       "euc-TW",
+       "EUCCN",
+       "EUCJP",
+       "EUCKR",
+       "EUCTW",
+       "EUC-CN",
+       "EUC-JP",
+       "EUC-KR",
+       "EUC-TW",
+};
+
+static GHashTable *vte_ambiguous_wide_codeset_table = NULL;
+
 /* Insert a single character into the stored data array. */
 static void
 vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
@@ -6088,6 +6116,7 @@ vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
                         gboolean paint_cells, gint forced_width)
 {
        GArray *array;
+       GQuark quark;
        struct vte_charcell cell, *pcell;
        int columns, i;
        long col;
@@ -6098,16 +6127,114 @@ vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
        insert = screen->insert_mode || force_insert_mode;
        invalidate_cells = insert || invalidate_cells;
 
-#ifdef VTE_DEBUG
-       if (_vte_debug_on(VTE_DEBUG_IO) && _vte_debug_on(VTE_DEBUG_PARSE)) {
-               fprintf(stderr, "Inserting %ld %c (%d/%d)(%d), delta = %ld, ",
-                       (long)c,
-                       c < 256 ? c : ' ',
-                       screen->defaults.fore, screen->defaults.back,
-                       vte_unichar_width(terminal, c),
-                       (long)screen->insert_delta);
+       /* If we've enabled the special drawing set, map the characters to
+        * Unicode. */
+       if (screen->defaults.alternate) {
+               switch (c) {
+               case 95:
+                       c = 0x0020; /* empty space */
+                       break;
+               case 96:
+                       c = 0x25c6; /* diamond */
+                       break;
+               case 'a':
+                       c = 0x2592; /* checkerboard */
+                       break;
+               case 'b':
+                       c = 0x2409; /* ht */
+                       break;
+               case 'c':
+                       c = 0x240c; /*  ff */
+                       break;
+               case 'd':
+                       c = 0x240d; /* cr */
+                       break;
+               case 'e':
+                       c = 0x240a; /* lf */
+                       break;
+               case 'f':
+                       c = 0x00b0; /* degree */
+                       break;
+               case 'g':
+                       c = 0x00b1; /* plus/minus */
+                       break;
+               case 'h':
+                       c = 0x2424; /* nl */
+                       break;
+               case 'i':
+                       c = 0x240b; /* vt */
+                       break;
+               case 'j':
+                       c = 0x2518; /* downright corner */
+                       break;
+               case 'k':
+                       c = 0x2510; /* upright corner */
+                       break;
+               case 'l':
+                       c = 0x250c; /* upleft corner */
+                       break;
+               case 'm':
+                       c = 0x2514; /* downleft corner */
+                       break;
+               case 'n':
+                       c = 0x253c; /* cross */
+                       break;
+               case 'o':
+                       c = 0x23ba; /* scanline 1/9 */
+                       break;
+               case 'p':
+                       c = 0x23bb; /* scanline 3/9 */
+                       break;
+               case 'q':
+                       c = 0x2500; /* horizontal line */
+                       break;
+               case 'r':
+                       c = 0x23bc; /* scanline 7/9 */
+                       break;
+               case 's':
+                       c = 0x23bd; /* scanline 9/9 */
+                       break;
+               case 't':
+                       c = 0x251c; /* left t (points right) */
+                       break;
+               case 'u':
+                       c = 0x2524; /* right t (points left) */
+                       break;
+               case 'v':
+                       c = 0x2534; /* bottom tee (points up) */
+                       break;
+               case 'w':
+                       c = 0x252c; /* top tee (points down) */
+                       break;
+               case 'x':
+                       c = 0x2502; /* vertical line */
+                       break;
+               case 'y':
+                       c = 0x2264; /* <= */
+                       break;
+               case 'z':
+                       c = 0x2265; /* >= */
+                       break;
+               case '{':
+                       c = 0x03c0; /* pi */
+                       break;
+               case '|':
+                       c = 0x2260; /* != */
+                       break;
+               case '}':
+                       c = 0x00a3; /* british pound */
+                       break;
+               case '~':
+                       c = 0x00b7; /* bullet */
+                       break;
+               case 127:
+                                 ; /* delete */
+                       break;
+               default:
+                       break;
+               }
        }
-#endif
+
        /* If this character is destined for the status line, save it. */
        if (terminal->pvt->screen->status_line) {
                g_string_append_unichar(terminal->pvt->screen->status_line_contents,
@@ -6118,10 +6245,37 @@ vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
 
        /* Figure out how many columns this character should occupy. */
        if (forced_width == -1) {
-               columns = vte_unichar_width(terminal, c);
+               if (VTE_ISO2022_HAS_WIDTH(c)) {
+                       columns = _vte_iso2022_get_width(c);
+               } else {
+                       /* The width of certain graphic characters changes
+                        * with the encoding, so override them here. */
+                       if (vte_unichar_isgraphic(c)) {
+                               quark = g_quark_from_string(terminal->pvt->encoding);
+                               if (g_hash_table_lookup(vte_ambiguous_wide_codeset_table,
+                                                       GINT_TO_POINTER(quark))) {
+                                       columns = 2;
+                               } else {
+                                       columns = 1;
+                               }
+                       } else {
+                               columns = vte_unichar_width(terminal, c);
+                       }
+               }
        } else {
                columns = forced_width;
        }
+       c &= ~(VTE_ISO2022_WIDTH_MASK);
+
+#ifdef VTE_DEBUG
+       if (_vte_debug_on(VTE_DEBUG_IO) && _vte_debug_on(VTE_DEBUG_PARSE)) {
+               fprintf(stderr, "Inserting %ld %c (%d/%d)(%d), delta = %ld, ",
+                       (long)c,
+                       c < 256 ? c : ' ',
+                       screen->defaults.fore, screen->defaults.back,
+                       columns, (long)screen->insert_delta);
+       }
+#endif
 
        /* If we're autowrapping here, do it. */
        col = screen->cursor_current.col;
@@ -6189,6 +6343,7 @@ vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
                pcell->c = cell.c;
                pcell->columns = cell.columns;
                pcell->fragment = cell.fragment;
+               pcell->alternate = 0;
 
                /* Now set the character and column count. */
                if (i == 0) {
@@ -6561,9 +6716,11 @@ vte_terminal_process_incoming(gpointer data)
        if (g_iconv(terminal->pvt->incoming_conv, &ibuf, &icount,
                    &obuf, &ocount) == -1) {
                /* No dice.  Try again when we have more data. */
-               if ((errno == EILSEQ) && (_vte_buffer_length(terminal->pvt->incoming) >= icount)) {
-                       /* Discard the offending byte. */
-                       start = _vte_buffer_length(terminal->pvt->incoming) - icount;
+               if ((errno == EILSEQ) &&
+                   (_vte_buffer_length(terminal->pvt->incoming) >= icount)) {
+                       /* Munge up the offending byte. */
+                       start = _vte_buffer_length(terminal->pvt->incoming) -
+                               icount;
 #ifdef VTE_DEBUG
                        if (_vte_debug_on(VTE_DEBUG_IO)) {
                                fprintf(stderr, "Error converting %ld incoming "
@@ -6577,7 +6734,8 @@ vte_terminal_process_incoming(gpointer data)
                        terminal->pvt->incoming->bytes[start] = '?';
                        /* Try again, before we try anything else.  To pull this
                         * off we add ourselves as a higher priority idle
-                        * handler, and cause this handler to be dropped. */
+                        * handler, and cause this lower-priority instance
+                        * to be dropped. */
                        terminal->pvt->processing_tag =
                                        g_idle_add_full(VTE_INPUT_RETRY_PRIORITY,
                                                        vte_terminal_process_incoming,
@@ -6615,7 +6773,7 @@ vte_terminal_process_incoming(gpointer data)
                substitutions = _vte_iso2022_copy(terminal->pvt->substitutions);
                substitution_count = _vte_iso2022_substitute(substitutions,
                                                             wbuf, wcount, wbuf,
-                                                            terminal->pvt->table);
+                                                            terminal->pvt->matcher);
                if (substitution_count < 0) {
                        _vte_iso2022_free(substitutions);
                        leftovers = TRUE;
@@ -6640,13 +6798,13 @@ vte_terminal_process_incoming(gpointer data)
        /* Try initial substrings. */
        while ((start < wcount) && !leftovers) {
                /* Try to match any control sequences. */
-               _vte_table_match(terminal->pvt->table,
-                                &wbuf[start],
-                                wcount - start,
-                                &match,
-                                &next,
-                                &quark,
-                                &params);
+               _vte_matcher_match(terminal->pvt->matcher,
+                                  &wbuf[start],
+                                  wcount - start,
+                                  &match,
+                                  &next,
+                                  &quark,
+                                  &params);
                /* We're in one of three possible situations now.
                 * First, the match string is a non-empty string and next
                 * points to the first character which isn't part of this
@@ -6770,7 +6928,7 @@ vte_terminal_process_incoming(gpointer data)
                /* There are leftovers, so convert them back to the terminal's
                 * old encoding and save them for later.  We can't use the
                 * scratch buffer here because it already holds ibuf. */
-               unconv = g_iconv_open(encoding, _vte_table_wide_encoding());
+               unconv = g_iconv_open(encoding, _vte_matcher_wide_encoding());
                if (unconv != ((GIConv) -1)) {
                        icount = sizeof(gunichar) * (wcount - start);
                        ibuf = (char*) &wbuf[start];
@@ -7075,13 +7233,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, _vte_table_wide_encoding()) == 0));
+                (strcmp(encoding, _vte_matcher_wide_encoding()) == 0));
 
        conv = NULL;
        if (strcmp(encoding, "UTF-8") == 0) {
                conv = &terminal->pvt->outgoing_conv_utf8;
        }
-       if (strcmp(encoding, _vte_table_wide_encoding()) == 0) {
+       if (strcmp(encoding, _vte_matcher_wide_encoding()) == 0) {
                conv = &terminal->pvt->outgoing_conv_wide;
        }
        g_assert(conv != NULL);
@@ -8252,7 +8410,6 @@ vte_terminal_get_text_range(VteTerminal *terminal,
                                attr.back.blue = back.blue;
                                attr.underline = pcell->underline;
                                attr.strikethrough = pcell->strikethrough;
-                               attr.alternate = pcell->alternate;
                                /* Store the character. */
                                string = g_string_append_unichar(string,
                                                                 pcell->c ?
@@ -9468,6 +9625,99 @@ xft_pattern_from_pango_font_desc(const PangoFontDescription *font_desc)
 }
 #endif
 
+#ifdef HAVE_XFT
+/* Use Xft's handy parse-this-xlfd function to convert the font description to
+ * an xlfd.  Apparently even font aliases work with this method. */
+static char *
+xlfd_from_pango_font_description(GtkWidget *widget,
+                                const PangoFontDescription *fontdesc)
+{
+       const char *ideal_family;
+       char **fonts, *family, *best;
+       int i, j, nfonts, size, ideal_size;
+       int weight, ideal_weight, pweight;
+       int slant, ideal_slant, pstyle;
+       long score, best_score;
+
+       best = NULL;
+       best_score = 0;
+       score = 0;
+       family = NULL;
+       size = 0;
+
+       /* Get the ideal family, size, weight. */
+       ideal_family = pango_font_description_get_family(fontdesc);
+       ideal_size = pango_font_description_get_size(fontdesc);
+       pweight = pango_font_description_get_weight(fontdesc);
+       ideal_weight = xft_weight_from_pango_weight(pweight);
+       pstyle = pango_font_description_get_style(fontdesc);
+       ideal_slant = xft_slant_from_pango_style(pstyle);
+
+       fonts = XListFonts(GDK_DISPLAY(), "*", -1, &nfonts);
+       if ((fonts == NULL) || (nfonts == 0)) {
+               return NULL;
+       }
+
+       for (i = 0; i < nfonts; i++) {
+               /* For each font, parse it into an Xft pattern, and give it
+                * a primitive score. */
+               XftPattern *candidate;
+               score = 0;
+               candidate = XftXlfdParse(strdup(fonts[i]), FALSE, FALSE);
+               if (candidate != NULL) {
+                       XftConfigSubstitute(candidate);
+                       j = 0;
+                       /* If you matched the family, you get many points. */
+                       while (XftPatternGetString(candidate, XFT_FAMILY,
+                                                  j, &family) == XftResultMatch) {
+                               if (strcasecmp(family, ideal_family) == 0) {
+                                       score += 1000000;
+                               }
+                               j++;
+                       }
+                       /* Deduct the square of the font size difference, if
+                        * we were given a size. */
+                       if (ideal_size != 0) {
+                               if (XftPatternGetInteger(candidate, XFT_SIZE,
+                                                        0, &size) == XftResultMatch) {
+                                       size *= PANGO_SCALE;
+                                       score -= (size - ideal_size) *
+                                                (size - ideal_size);
+                               }
+                       }
+                       /* Deduct the square of the weight difference. */
+                       if (XftPatternGetInteger(candidate, XFT_WEIGHT,
+                                                0, &weight) == XftResultMatch) {
+                               score -= (weight - ideal_weight) *
+                                        (weight - ideal_weight);
+                       }
+                       /* Deduct the square of the slant difference. */
+                       if (XftPatternGetInteger(candidate, XFT_SLANT,
+                                                0, &slant) == XftResultMatch) {
+                               score -= (slant - ideal_slant) *
+                                        (slant - ideal_slant);
+                       }
+                       /* Minimum score is zero. */
+                       score = MAX(0, score);
+
+                       if (score > best_score) {
+                               /* This is our current guess for best match. */
+                               if (best != NULL) {
+                                       free(best);
+                               }
+                               best = strdup(fonts[i]);
+                               best_score = score;
+                       }
+                       XftPatternDestroy(candidate);
+                       candidate = NULL;
+               }
+       }
+
+       XFreeFontNames(fonts);
+
+       return best;
+}
+#else
 static char *
 xlfd_from_pango_font_description(GtkWidget *widget,
                                 const PangoFontDescription *fontdesc)
@@ -9579,6 +9829,7 @@ xlfd_from_pango_font_description(GtkWidget *widget,
        g_free(xlfd);
        return ret;
 }
+#endif
 
 #ifdef HAVE_XFT
 /* Convert an Xft pattern to a font name. */
@@ -10445,10 +10696,10 @@ vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
        vte_terminal_set_termcap(terminal, NULL, FALSE);
 
        /* Create a table to hold the control sequences. */
-       if (terminal->pvt->table != NULL) {
-               _vte_table_free(terminal->pvt->table);
+       if (terminal->pvt->matcher != NULL) {
+               _vte_matcher_free(terminal->pvt->matcher);
        }
-       terminal->pvt->table = _vte_table_new();
+       terminal->pvt->matcher = _vte_matcher_new(emulation);
 
        /* Create a tree to hold the handlers. */
        if (terminal->pvt->sequences) {
@@ -10478,10 +10729,9 @@ vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
                                               code);
                if ((tmp != NULL) && (tmp[0] != '\0')) {
                        _vte_termcap_strip(tmp, &stripped, &stripped_length);
-                       _vte_table_add(terminal->pvt->table,
-                                      stripped, stripped_length,
-                                      code,
-                                      0);
+                       _vte_matcher_add(terminal->pvt->matcher,
+                                        stripped, stripped_length,
+                                        code, 0);
                        if (stripped[0] == '\r') {
                                found_cr = TRUE;
                        } else
@@ -10505,25 +10755,25 @@ vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
                        code = _vte_xterm_capability_strings[i].code;
                        value = _vte_xterm_capability_strings[i].value;
                        _vte_termcap_strip(code, &stripped, &stripped_length);
-                       _vte_table_add(terminal->pvt->table,
-                                      stripped, stripped_length,
-                                      value, 0);
+                       _vte_matcher_add(terminal->pvt->matcher,
+                                        stripped, stripped_length,
+                                        value, 0);
                        g_free(stripped);
                }
        }
 
        /* Always define cr and lf. */
        if (!found_cr) {
-               _vte_table_add(terminal->pvt->table, "\r", 1, "cr", 0);
+               _vte_matcher_add(terminal->pvt->matcher, "\r", 1, "cr", 0);
        }
        if (!found_lf) {
-               _vte_table_add(terminal->pvt->table, "\n", 1, "sf", 0);
+               _vte_matcher_add(terminal->pvt->matcher, "\n", 1, "sf", 0);
        }
 
 #ifdef VTE_DEBUG
        if (_vte_debug_on(VTE_DEBUG_MISC)) {
                fprintf(stderr, "Trie contents:\n");
-               _vte_table_print(terminal->pvt->table);
+               _vte_matcher_print(terminal->pvt->matcher);
                fprintf(stderr, "\n");
        }
 #endif
@@ -10673,7 +10923,7 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
 
        /* Load the termcap data and set up the emulation. */
        pvt->termcap = NULL;
-       pvt->table = NULL;
+       pvt->matcher = NULL;
        pvt->termcap_path = NULL;
        memset(&pvt->flags, 0, sizeof(pvt->flags));
        pvt->flags.am = FALSE;
@@ -10730,6 +10980,7 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
 
        /* Set up I/O encodings. */
        pvt->encoding = NULL;
+       pvt->encodingq = 0;
        pvt->substitutions = _vte_iso2022_new();
        pvt->incoming = _vte_buffer_new();
        pvt->processing = FALSE;
@@ -11387,9 +11638,9 @@ vte_terminal_finalize(GObject *object)
        terminal->pvt->sequences= NULL;
        terminal->pvt->emulation = NULL;
        terminal->pvt->termcap_path = NULL;
-       if (terminal->pvt->table != NULL) {
-               _vte_table_free(terminal->pvt->table);
-               terminal->pvt->table = NULL;
+       if (terminal->pvt->matcher != NULL) {
+               _vte_matcher_free(terminal->pvt->matcher);
+               terminal->pvt->matcher = NULL;
        }
        _vte_termcap_free(terminal->pvt->termcap);
        terminal->pvt->termcap = NULL;
@@ -11631,28 +11882,20 @@ vte_terminal_xft_remap_char(Display *display, XftFont *font, XftChar32 orig)
 static gboolean
 vte_unichar_isgraphic(gunichar c)
 {
+       if ((c >= 0x2500) && (c <= 0x257f)) {
+               return TRUE;
+       }
        switch (c) {
-       case 0x2500: /* horizontal line */
-       case 0x2502: /* vertical line */
-       case 0x250c: /* upleft corner */
-       case 0x2510: /* upright corner */
-       case 0x2514: /* downleft corner */
-       case 0x2518: /* downright corner */
-       case 0x2524: /* right t */
-       case 0x251c: /* left t */
-       case 0x2534: /* up tee */
-       case 0x252c: /* down tee */
-       case 0x253c: /* cross */
-       case 0x2592: /* checkerboard */
-       case 0x25c6: /* diamond */
        case 0x00b0: /* degree */
        case 0x00b1: /* plus/minus */
        case 0x00b7: /* bullet */
        case 0x2190: /* left arrow */
+       case 0x2191: /* up arrow */
        case 0x2192: /* right arrow */
        case 0x2193: /* down arrow */
-       case 0x2191: /* up arrow */
-       case 0x25ae: /* block */
+       case 0x2260: /* != */
+       case 0x2264: /* <= */
+       case 0x2265: /* >= */
        case 0x23ba: /* scanline 1/9 */
        case 0x23bb: /* scanline 3/9 */
        case 0x23bc: /* scanline 7/9 */
@@ -11663,9 +11906,6 @@ vte_unichar_isgraphic(gunichar c)
        case 0x240c: /* FF symbol */
        case 0x240d: /* CR symbol */
        case 0x2424: /* NL symbol */
-       case 0x2264: /* <= */
-       case 0x2265: /* >= */
-       case 0x2260: /* != */
                return TRUE;
                break;
        default:
@@ -11674,8 +11914,9 @@ vte_unichar_isgraphic(gunichar c)
        return FALSE;
 }
 
-/* Draw the graphic representation of an alternate font graphics character. */
-static void
+/* Draw the graphic representation of a line-drawing or special graphics
+ * character. */
+static gboolean
 vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                          gint fore, gint back, gboolean draw_default_bg,
                          gint x, gint y, gint column_width, gint row_height,
@@ -11683,112 +11924,13 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                          GdkDrawable *gdrawable, Drawable drawable,
                          GdkGC *ggc, GC gc)
 {
+       gboolean ret;
        XPoint diamond[4];
        gint xcenter, xright, ycenter, ybottom, i, j, draw;
 
        x += VTE_PAD_WIDTH;
        y += VTE_PAD_WIDTH;
 
-       /* If this is a unicode special graphics character, map it to one of
-        * the characters we know how to draw. */
-       switch (c) {
-       case 0x2500: /* horizontal line */
-               c = 'q';
-               break;
-       case 0x2502: /* vertical line */
-               c = 'x';
-               break;
-       case 0x250c: /* upleft corner */
-               c = 'l';
-               break;
-       case 0x2510: /* upright corner */
-               c = 'k';
-               break;
-       case 0x2514: /* downleft corner */
-               c = 'm';
-               break;
-       case 0x2518: /* downright corner */
-               c = 'j';
-               break;
-       case 0x2524: /* right t (points left) */
-               c = 'u';
-               break;
-       case 0x251c: /* left t (points right) */
-               c = 't';
-               break;
-       case 0x2534: /* bottom tee (points up) */
-               c = 'v';
-               break;
-       case 0x252c: /* top tee (points down) */
-               c = 'w';
-               break;
-       case 0x253c: /* cross */
-               c = 'n';
-               break;
-       case 0x2592: /* checkerboard */
-               c = 'a';
-               break;
-       case 0x25c6: /* diamond */
-               c = 96;
-               break;
-       case 0x00b0: /* degree */
-               c = 'f';
-               break;
-       case 0x00b1: /* plus/minus */
-               c = 'g';
-               break;
-       case 0x00b7: /* bullet */
-               c = 126;
-               break;
-       case 0x23ba: /* scanline 1/9 */
-               c = 'o';
-               break;
-       case 0x23bb: /* scanline 3/9 */
-               c = 'p';
-               break;
-       case 0x23bc: /* scanline 7/9 */
-               c = 'r';
-               break;
-       case 0x23bd: /* scanline 9/9 */
-               c = 's';
-               break;
-       case 0x2409: /* ht */
-               c = 'b';
-               break;
-       case 0x240c: /*  ff */
-               c = 'c';
-               break;
-       case 0x240d: /* cr */
-               c = 'd';
-               break;
-       case 0x240a: /* lf */
-               c = 'e';
-               break;
-       case 0x2424: /* nl */
-               c = 'h';
-               break;
-       case 0x240b: /* vt */
-               c = 'i';
-               break;
-       case 0x2264: /* <= */
-               c = 'y';
-               break;
-       case 0x2265: /* >= */
-               c = 'z';
-               break;
-       case 0x2260: /* != */
-               c = '|';
-               break;
-
-       case 0x2190: /* left arrow */
-       case 0x2192: /* right arrow */
-       case 0x2193: /* down arrow */
-       case 0x2191: /* up arrow */
-       case 0x25ae: /* block */
-       default:
-               break;
-       }
-
        xright = x + column_width;
        ybottom = y + row_height;
        xcenter = (x + xright) / 2;
@@ -11797,148 +11939,96 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
        if ((back != VTE_DEF_BG) || draw_default_bg) {
                XSetForeground(display, gc, terminal->pvt->palette[back].pixel);
                XFillRectangle(display, drawable, gc,
-                              x, y,
-                              column_width, row_height);
+                              x, y, column_width, row_height);
        }
+
        XSetForeground(display, gc, terminal->pvt->palette[fore].pixel);
+
+       ret = TRUE;
+
        switch (c) {
-       case 0x25ae: /* solid rectangle */
-               XFillRectangle(display, drawable, gc, x, y,
-                              xright - x, ybottom - y);
-               break;
-       case 95:
-               /* drawing a blank */
-               break;
-       case 96:
-               /* diamond */
-               diamond[0].x = xcenter;
-               diamond[0].y = y + 1;
-               diamond[1].x = xright - 1;
-               diamond[1].y = ycenter;
-               diamond[2].x = xcenter;
-               diamond[2].y = ybottom - 1;
-               diamond[3].x = x + 1;
-               diamond[3].y = ycenter;
-               XFillPolygon(display, drawable, gc,
-                            diamond, 4,
-                            Convex, CoordModeOrigin);
-               break;
-       case 97:  /* a */
-               for (i = x; i <= xright; i++) {
-                       draw = ((i - x) & 1) == 0;
-                       for (j = y; j < ybottom; j++) {
-                               if (draw) {
-                                       XDrawPoint(display, drawable, gc, i, j);
-                               }
-                               draw = !draw;
-                       }
-               }
-               break;
-       case 98:  /* b */
+       case 0x3c0: /* pi */
                xcenter--;
                ycenter--;
                xright--;
                ybottom--;
-               /* H */
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         x, ycenter);
                XDrawLine(display, drawable, gc,
-                         xcenter, y,
-                         xcenter, ycenter);
-               XDrawLine(display, drawable, gc,
-                         x, (y + ycenter) / 2,
-                         xcenter, (y + ycenter) / 2);
-               /* T */
+                         (x + xcenter) / 2 - 1,
+                         (y + ycenter) / 2,
+                         (xright + xcenter) / 2 + 1,
+                         (y + ycenter) / 2);
                XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
-                         xright - 1, ycenter);
+                         (x + xcenter) / 2,
+                         (y + ycenter) / 2,
+                         (x + xcenter) / 2,
+                         (ybottom + ycenter) / 2);
                XDrawLine(display, drawable, gc,
-                         (xcenter + xright) / 2, ycenter,
-                         (xcenter + xright) / 2, ybottom - 1);
+                         (xright + xcenter) / 2,
+                         (y + ycenter) / 2,
+                         (xright + xcenter) / 2,
+                         (ybottom + ycenter) / 2);
                break;
-       case 99:  /* c */
+       case 124:
                xcenter--;
                ycenter--;
                xright--;
                ybottom--;
-               /* F */
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         x, ycenter);
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         xcenter, y);
-               XDrawLine(display, drawable, gc,
-                         x, (y + ycenter) / 2,
-                         xcenter, (y + ycenter) / 2);
-               /* F */
+               /* != */
                XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
-                         xcenter, ybottom - 1);
+                         (x + xcenter) / 2 - 1, ycenter,
+                         (xright + xcenter) / 2 + 1, ycenter);
                XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
-                         xright - 1, ycenter);
+                         (x + xcenter) / 2 - 1,
+                         (ybottom + ycenter) / 2,
+                         (xright + xcenter) / 2 + 1,
+                         (ybottom + ycenter) / 2);
                XDrawLine(display, drawable, gc,
-                         xcenter, (ycenter + ybottom) / 2,
-                         xright - 1, (ycenter + ybottom) / 2);
+                         xright - 1, y + 1,
+                         x + 1, ybottom - 1);
                break;
-       case 100: /* d */
+       case 127:
                xcenter--;
                ycenter--;
                xright--;
                ybottom--;
-               /* C */
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         x, ycenter);
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         xcenter, y);
+               /* A "delete" symbol I saw somewhere. */
                XDrawLine(display, drawable, gc,
                          x, ycenter,
-                         xcenter, ycenter);
-               /* R */
-               XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
-                         xcenter, ybottom - 1);
+                         xcenter, y);
                XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
+                         xcenter, y,
                          xright - 1, ycenter);
                XDrawLine(display, drawable, gc,
                          xright - 1, ycenter,
-                         xright - 1, (ycenter + ybottom) / 2);
+                         xright - 1, ybottom - 1);
                XDrawLine(display, drawable, gc,
-                         xright - 1, (ycenter + ybottom) / 2,
-                         xcenter, (ycenter + ybottom) / 2);
+                         xright - 1, ybottom - 1,
+                         x, ybottom - 1);
                XDrawLine(display, drawable, gc,
-                         xcenter, (ycenter + ybottom) / 2,
-                         xright - 1, ybottom - 1);
+                         x, ybottom - 1,
+                         x, ycenter);
                break;
-       case 101: /* e */
+       case 0x00a3:
                xcenter--;
                ycenter--;
                xright--;
                ybottom--;
-               /* L */
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         x, ycenter);
-               XDrawLine(display, drawable, gc,
-                         x, ycenter,
-                         xcenter, ycenter);
-               /* F */
+               /* British pound.  An "L" with a hyphen. */
                XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
-                         xcenter, ybottom - 1);
+                         (x + xcenter) / 2,
+                         (y + ycenter) / 2,
+                         (x + xcenter) / 2,
+                         (ycenter + ybottom) / 2);
                XDrawLine(display, drawable, gc,
-                         xcenter, ycenter,
-                         xright - 1, ycenter);
+                         (x + xcenter) / 2,
+                         (ycenter + ybottom) / 2,
+                         (xcenter + xright) / 2,
+                         (ycenter + ybottom) / 2);
                XDrawLine(display, drawable, gc,
-                         xcenter, (ycenter + ybottom) / 2,
-                         xright - 1, (ycenter + ybottom) / 2);
+                         x, ycenter,
+                         xcenter + 1, ycenter);
                break;
-       case 102: /* f */
+       case 0x00b0: /* f */
                /* litle circle */
                diamond[0].x = xcenter - 1;
                diamond[0].y = ycenter;
@@ -11952,7 +12042,7 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                             diamond, 4,
                             Convex, CoordModeOrigin);
                break;
-       case 103: /* g */
+       case 0x00b1: /* g */
                xcenter--;
                ycenter--;
                xright--;
@@ -11970,30 +12060,131 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                          (xcenter + xright) / 2,
                          (ycenter + ybottom) / 2);
                break;
-       case 104: /* h */
+       case 0x00b7:
                xcenter--;
                ycenter--;
                xright--;
                ybottom--;
-               /* N */
+               /* short hyphen? */
+               XDrawLine(display, drawable, gc,
+                         xcenter - 1, ycenter,
+                         xcenter + 1, ycenter);
+               break;
+       case 0x2264: /* y */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
+               /* <= */
+               XDrawLine(display, drawable, gc,
+                         xright - 1, y,
+                         x, (y + ycenter) / 2);
+               XDrawLine(display, drawable, gc,
+                         x, (y + ycenter) / 2,
+                         xright - 1, ycenter);
+               XDrawLine(display, drawable, gc,
+                         x, ycenter,
+                         xright - 1, (ycenter + ybottom) / 2);
+               break;
+       case 0x2265: /* z */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
+               /* >= */
                XDrawLine(display, drawable, gc,
                          x, y,
+                         xright - 1, (y + ycenter) / 2);
+               XDrawLine(display, drawable, gc,
+                         xright - 1, (y + ycenter) / 2,
                          x, ycenter);
+               XDrawLine(display, drawable, gc,
+                         xright - 1, ycenter,
+                         x, (ycenter + ybottom) / 2);
+               break;
+       case 0x23ba: /* o */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              y,
+                              column_width,
+                              VTE_LINE_WIDTH);
+               break;
+       case 0x23bb: /* p */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              (y + ycenter) / 2,
+                              column_width,
+                              VTE_LINE_WIDTH);
+               break;
+       case 0x23bc: /* r */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              (ycenter + ybottom) / 2,
+                              column_width,
+                              VTE_LINE_WIDTH);
+               break;
+       case 0x23bd: /* s */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              ybottom-1,
+                              column_width,
+                              VTE_LINE_WIDTH);
+               break;
+       case 0x2409:  /* b */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
+               /* H */
                XDrawLine(display, drawable, gc,
                          x, y,
-                         xcenter, ycenter);
+                         x, ycenter);
                XDrawLine(display, drawable, gc,
                          xcenter, y,
                          xcenter, ycenter);
+               XDrawLine(display, drawable, gc,
+                         x, (y + ycenter) / 2,
+                         xcenter, (y + ycenter) / 2);
+               /* T */
+               XDrawLine(display, drawable, gc,
+                         xcenter, ycenter,
+                         xright - 1, ycenter);
+               XDrawLine(display, drawable, gc,
+                         (xcenter + xright) / 2, ycenter,
+                         (xcenter + xright) / 2, ybottom - 1);
+               break;
+       case 0x240a: /* e */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
                /* L */
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         x, ycenter);
+               XDrawLine(display, drawable, gc,
+                         x, ycenter,
+                         xcenter, ycenter);
+               /* F */
                XDrawLine(display, drawable, gc,
                          xcenter, ycenter,
                          xcenter, ybottom - 1);
                XDrawLine(display, drawable, gc,
-                         xcenter, ybottom - 1,
-                         xright - 1, ybottom - 1);
+                         xcenter, ycenter,
+                         xright - 1, ycenter);
+               XDrawLine(display, drawable, gc,
+                         xcenter, (ycenter + ybottom) / 2,
+                         xright - 1, (ycenter + ybottom) / 2);
                break;
-       case 105: /* i */
+       case 0x240b: /* i */
                xcenter--;
                ycenter--;
                xright--;
@@ -12013,23 +12204,156 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                          (xcenter + xright) / 2, ycenter,
                          (xcenter + xright) / 2, ybottom - 1);
                break;
-       case 106: /* j */
+       case 0x240c:  /* c */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
+               /* F */
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         x, ycenter);
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         xcenter, y);
+               XDrawLine(display, drawable, gc,
+                         x, (y + ycenter) / 2,
+                         xcenter, (y + ycenter) / 2);
+               /* F */
+               XDrawLine(display, drawable, gc,
+                         xcenter, ycenter,
+                         xcenter, ybottom - 1);
+               XDrawLine(display, drawable, gc,
+                         xcenter, ycenter,
+                         xright - 1, ycenter);
+               XDrawLine(display, drawable, gc,
+                         xcenter, (ycenter + ybottom) / 2,
+                         xright - 1, (ycenter + ybottom) / 2);
+               break;
+       case 0x240d: /* d */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
+               /* C */
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         x, ycenter);
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         xcenter, y);
+               XDrawLine(display, drawable, gc,
+                         x, ycenter,
+                         xcenter, ycenter);
+               /* R */
+               XDrawLine(display, drawable, gc,
+                         xcenter, ycenter,
+                         xcenter, ybottom - 1);
+               XDrawLine(display, drawable, gc,
+                         xcenter, ycenter,
+                         xright - 1, ycenter);
+               XDrawLine(display, drawable, gc,
+                         xright - 1, ycenter,
+                         xright - 1, (ycenter + ybottom) / 2);
+               XDrawLine(display, drawable, gc,
+                         xright - 1, (ycenter + ybottom) / 2,
+                         xcenter, (ycenter + ybottom) / 2);
+               XDrawLine(display, drawable, gc,
+                         xcenter, (ycenter + ybottom) / 2,
+                         xright - 1, ybottom - 1);
+               break;
+       case 0x2424: /* h */
+               xcenter--;
+               ycenter--;
+               xright--;
+               ybottom--;
+               /* N */
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         x, ycenter);
+               XDrawLine(display, drawable, gc,
+                         x, y,
+                         xcenter, ycenter);
+               XDrawLine(display, drawable, gc,
+                         xcenter, y,
+                         xcenter, ycenter);
+               /* L */
+               XDrawLine(display, drawable, gc,
+                         xcenter, ycenter,
+                         xcenter, ybottom - 1);
+               XDrawLine(display, drawable, gc,
+                         xcenter, ybottom - 1,
+                         xright - 1, ybottom - 1);
+               break;
+       case 0x2500: /* q */
                XFillRectangle(display,
                               drawable,
                               gc,
                               x,
                               ycenter,
-                              xcenter - x + VTE_LINE_WIDTH,
+                              column_width,
                               VTE_LINE_WIDTH);
+               break;
+       case 0x2501:
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              ycenter,
+                              column_width,
+                              VTE_LINE_WIDTH * 2);
+               break;
+       case 0x2502: /* x */
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
                               y,
                               VTE_LINE_WIDTH,
-                              ycenter - y + VTE_LINE_WIDTH);
+                              row_height);
+               break;
+       case 0x2503:
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              y,
+                              VTE_LINE_WIDTH * 2,
+                              row_height);
                break;
-       case 107: /* k */
+       case 0x250c: /* l */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              xright - xcenter,
+                              VTE_LINE_WIDTH);
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              VTE_LINE_WIDTH,
+                              ybottom - ycenter);
+               break;
+       case 0x250f:
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              xright - xcenter,
+                              VTE_LINE_WIDTH * 2);
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              VTE_LINE_WIDTH * 2,
+                              ybottom - ycenter);
+               break;
+       case 0x2510: /* k */
                XFillRectangle(display,
                               drawable,
                               gc,
@@ -12041,43 +12365,91 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                               drawable,
                               gc,
                               xcenter,
-                              ycenter,
-                              VTE_LINE_WIDTH,
-                              ybottom - ycenter);
+                              ycenter,
+                              VTE_LINE_WIDTH,
+                              ybottom - ycenter);
+               break;
+       case 0x2513:
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              ycenter,
+                              xcenter - x + VTE_LINE_WIDTH * 2,
+                              VTE_LINE_WIDTH * 2);
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              VTE_LINE_WIDTH * 2,
+                              ybottom - ycenter);
+               break;
+       case 0x2514: /* m */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              xright - xcenter,
+                              VTE_LINE_WIDTH);
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              y,
+                              VTE_LINE_WIDTH,
+                              ycenter - y + VTE_LINE_WIDTH);
+               break;
+       case 0x2517:
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              ycenter,
+                              xright - xcenter,
+                              VTE_LINE_WIDTH * 2);
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              y,
+                              VTE_LINE_WIDTH * 2,
+                              ycenter - y + VTE_LINE_WIDTH * 2);
                break;
-       case 108: /* l */
+       case 0x2518: /* j */
                XFillRectangle(display,
                               drawable,
                               gc,
-                              xcenter,
+                              x,
                               ycenter,
-                              xright - xcenter,
+                              xcenter - x + VTE_LINE_WIDTH,
                               VTE_LINE_WIDTH);
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
-                              ycenter,
+                              y,
                               VTE_LINE_WIDTH,
-                              ybottom - ycenter);
+                              ycenter - y + VTE_LINE_WIDTH);
                break;
-       case 109: /* m */
+       case 0x251b:
                XFillRectangle(display,
                               drawable,
                               gc,
-                              xcenter,
+                              x,
                               ycenter,
-                              xright - xcenter,
-                              VTE_LINE_WIDTH);
+                              xcenter - x + VTE_LINE_WIDTH * 2,
+                              VTE_LINE_WIDTH * 2);
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
                               y,
-                              VTE_LINE_WIDTH,
-                              ycenter - y + VTE_LINE_WIDTH);
+                              VTE_LINE_WIDTH * 2,
+                              ycenter - y + VTE_LINE_WIDTH * 2);
                break;
-       case 110: /* n */
+       case 0x251c: /* t */
                XFillRectangle(display,
                               drawable,
                               gc,
@@ -12088,89 +12460,92 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                XFillRectangle(display,
                               drawable,
                               gc,
-                              x,
+                              xcenter,
                               ycenter,
-                              column_width,
+                              xright - xcenter,
                               VTE_LINE_WIDTH);
                break;
-       case 111: /* o */
+       case 0x2523:
                XFillRectangle(display,
                               drawable,
                               gc,
-                              x,
+                              xcenter,
                               y,
-                              column_width,
-                              VTE_LINE_WIDTH);
-               break;
-       case 112: /* p */
+                              VTE_LINE_WIDTH * 2,
+                              row_height);
                XFillRectangle(display,
                               drawable,
                               gc,
-                              x,
-                              (y + ycenter) / 2,
-                              column_width,
-                              VTE_LINE_WIDTH);
+                              xcenter,
+                              ycenter,
+                              xright - xcenter,
+                              VTE_LINE_WIDTH * 2);
                break;
-       case 113: /* q */
+       case 0x2524: /* u */
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              xcenter,
+                              y,
+                              VTE_LINE_WIDTH,
+                              row_height);
                XFillRectangle(display,
                               drawable,
                               gc,
                               x,
                               ycenter,
-                              column_width,
+                              xcenter - x + VTE_LINE_WIDTH,
                               VTE_LINE_WIDTH);
                break;
-       case 114: /* r */
+       case 0x252b:
                XFillRectangle(display,
                               drawable,
                               gc,
-                              x,
-                              (ycenter + ybottom) / 2,
-                              column_width,
-                              VTE_LINE_WIDTH);
-               break;
-       case 115: /* s */
+                              xcenter,
+                              y,
+                              VTE_LINE_WIDTH * 2,
+                              row_height);
                XFillRectangle(display,
                               drawable,
                               gc,
                               x,
-                              ybottom-1,
-                              column_width,
-                              VTE_LINE_WIDTH);
+                              ycenter,
+                              xcenter - x + VTE_LINE_WIDTH * 2,
+                              VTE_LINE_WIDTH * 2);
                break;
-       case 116: /* t */
+       case 0x252c: /* w */
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
-                              y,
+                              ycenter,
                               VTE_LINE_WIDTH,
-                              row_height);
+                              ybottom - ycenter);
                XFillRectangle(display,
                               drawable,
                               gc,
-                              xcenter,
+                              x,
                               ycenter,
-                              xright - xcenter,
+                              column_width,
                               VTE_LINE_WIDTH);
                break;
-       case 117: /* u */
+       case 0x2533:
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
-                              y,
-                              VTE_LINE_WIDTH,
-                              row_height);
+                              ycenter,
+                              VTE_LINE_WIDTH * 2,
+                              ybottom - ycenter);
                XFillRectangle(display,
                               drawable,
                               gc,
                               x,
                               ycenter,
-                              xcenter - x + VTE_LINE_WIDTH,
-                              VTE_LINE_WIDTH);
+                              column_width,
+                              VTE_LINE_WIDTH * 2);
                break;
-       case 118: /* v */
+       case 0x2534: /* v */
                XFillRectangle(display,
                               drawable,
                               gc,
@@ -12186,14 +12561,14 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                               column_width,
                               VTE_LINE_WIDTH);
                break;
-       case 119: /* w */
+       case 0x253c: /* n */
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
-                              ycenter,
+                              y,
                               VTE_LINE_WIDTH,
-                              ybottom - ycenter);
+                              row_height);
                XFillRectangle(display,
                               drawable,
                               gc,
@@ -12202,141 +12577,56 @@ vte_terminal_draw_graphic(VteTerminal *terminal, gunichar c,
                               column_width,
                               VTE_LINE_WIDTH);
                break;
-       case 120: /* x */
+       case 0x254b:
                XFillRectangle(display,
                               drawable,
                               gc,
                               xcenter,
                               y,
-                              VTE_LINE_WIDTH,
+                              VTE_LINE_WIDTH * 2,
                               row_height);
+               XFillRectangle(display,
+                              drawable,
+                              gc,
+                              x,
+                              ycenter,
+                              column_width,
+                              VTE_LINE_WIDTH * 2);
                break;
-       case 121: /* y */
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               /* <= */
-               XDrawLine(display, drawable, gc,
-                         xright - 1, y,
-                         x, (y + ycenter) / 2);
-               XDrawLine(display, drawable, gc,
-                         x, (y + ycenter) / 2,
-                         xright - 1, ycenter);
-               XDrawLine(display, drawable, gc,
-                         x, ycenter,
-                         xright - 1, (ycenter + ybottom) / 2);
-               break;
-       case 122: /* z */
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               /* >= */
-               XDrawLine(display, drawable, gc,
-                         x, y,
-                         xright - 1, (y + ycenter) / 2);
-               XDrawLine(display, drawable, gc,
-                         xright - 1, (y + ycenter) / 2,
-                         x, ycenter);
-               XDrawLine(display, drawable, gc,
-                         xright - 1, ycenter,
-                         x, (ycenter + ybottom) / 2);
-               break;
-       case 123: /* pi */
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               XDrawLine(display, drawable, gc,
-                         (x + xcenter) / 2 - 1,
-                         (y + ycenter) / 2,
-                         (xright + xcenter) / 2 + 1,
-                         (y + ycenter) / 2);
-               XDrawLine(display, drawable, gc,
-                         (x + xcenter) / 2,
-                         (y + ycenter) / 2,
-                         (x + xcenter) / 2,
-                         (ybottom + ycenter) / 2);
-               XDrawLine(display, drawable, gc,
-                         (xright + xcenter) / 2,
-                         (y + ycenter) / 2,
-                         (xright + xcenter) / 2,
-                         (ybottom + ycenter) / 2);
-               break;
-       case 124:
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               /* != */
-               XDrawLine(display, drawable, gc,
-                         (x + xcenter) / 2 - 1, ycenter,
-                         (xright + xcenter) / 2 + 1, ycenter);
-               XDrawLine(display, drawable, gc,
-                         (x + xcenter) / 2 - 1,
-                         (ybottom + ycenter) / 2,
-                         (xright + xcenter) / 2 + 1,
-                         (ybottom + ycenter) / 2);
-               XDrawLine(display, drawable, gc,
-                         xright - 1, y + 1,
-                         x + 1, ybottom - 1);
-               break;
-       case 125:
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               /* British pound.  An "L" with a hyphen. */
-               XDrawLine(display, drawable, gc,
-                         (x + xcenter) / 2,
-                         (y + ycenter) / 2,
-                         (x + xcenter) / 2,
-                         (ycenter + ybottom) / 2);
-               XDrawLine(display, drawable, gc,
-                         (x + xcenter) / 2,
-                         (ycenter + ybottom) / 2,
-                         (xcenter + xright) / 2,
-                         (ycenter + ybottom) / 2);
-               XDrawLine(display, drawable, gc,
-                         x, ycenter,
-                         xcenter + 1, ycenter);
+       case 0x2592:  /* a */
+               for (i = x; i <= xright; i++) {
+                       draw = ((i - x) & 1) == 0;
+                       for (j = y; j < ybottom; j++) {
+                               if (draw) {
+                                       XDrawPoint(display, drawable, gc, i, j);
+                               }
+                               draw = !draw;
+                       }
+               }
                break;
-       case 126:
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               /* short hyphen? */
-               XDrawLine(display, drawable, gc,
-                         xcenter - 1, ycenter,
-                         xcenter + 1, ycenter);
+       case 0x25ae: /* solid rectangle */
+               XFillRectangle(display, drawable, gc, x, y,
+                              xright - x, ybottom - y);
                break;
-       case 127:
-               xcenter--;
-               ycenter--;
-               xright--;
-               ybottom--;
-               /* A "delete" symbol I saw somewhere. */
-               XDrawLine(display, drawable, gc,
-                         x, ycenter,
-                         xcenter, y);
-               XDrawLine(display, drawable, gc,
-                         xcenter, y,
-                         xright - 1, ycenter);
-               XDrawLine(display, drawable, gc,
-                         xright - 1, ycenter,
-                         xright - 1, ybottom - 1);
-               XDrawLine(display, drawable, gc,
-                         xright - 1, ybottom - 1,
-                         x, ybottom - 1);
-               XDrawLine(display, drawable, gc,
-                         x, ybottom - 1,
-                         x, ycenter);
+       case 0x25c6:
+               /* diamond */
+               diamond[0].x = xcenter;
+               diamond[0].y = y + 1;
+               diamond[1].x = xright - 1;
+               diamond[1].y = ycenter;
+               diamond[2].x = xcenter;
+               diamond[2].y = ybottom - 1;
+               diamond[3].x = x + 1;
+               diamond[3].y = ycenter;
+               XFillPolygon(display, drawable, gc,
+                            diamond, 4,
+                            Convex, CoordModeOrigin);
                break;
        default:
+               ret = FALSE;
                break;
        }
+       return ret;
 }
 
 /* Calculate how much padding needs to be placed to either side of a character
@@ -12829,7 +13119,7 @@ vte_terminal_draw_row(VteTerminal *terminal,
        GArray *items;
        int i, j, fore, nfore, back, nback;
        gboolean underline, nunderline, bold, nbold, hilite, nhilite, reverse,
-                strikethrough, nstrikethrough;
+                strikethrough, nstrikethrough, drawn;
        struct vte_draw_item item;
        struct vte_charcell *cell;
 
@@ -12870,22 +13160,51 @@ vte_terminal_draw_row(VteTerminal *terminal,
                }
 
                /* If this is a graphics character, draw it locally. */
-               if ((cell != NULL) &&
-                   (cell->alternate || vte_unichar_isgraphic(cell->c))) {
+               if ((cell != NULL) && vte_unichar_isgraphic(cell->c)) {
                        item.c = cell ? cell->c : ' ';
                        item.columns = cell ? cell->columns : 1;
-                       vte_terminal_draw_graphic(terminal, cell->c, fore, back,
-                                                 FALSE,
-                                                 x +
-                                                 ((i - column) * column_width),
-                                                 y,
-                                                 item.columns * column_width,
-                                                 row_height,
-                                                 display,
-                                                 gdrawable,
-                                                 drawable,
-                                                 ggc,
-                                                 gc);
+                       drawn = vte_terminal_draw_graphic(terminal, cell->c, fore, back,
+                                                         FALSE,
+                                                         x +
+                                                         ((i - column) * column_width),
+                                                         y,
+                                                         item.columns * column_width,
+                                                         row_height,
+                                                         display,
+                                                         gdrawable,
+                                                         drawable,
+                                                         ggc,
+                                                         gc);
+                       if (!drawn) {
+                               item.xpad = vte_terminal_get_char_padding(terminal,
+                                                                         display,
+                                                                         item.c);
+                               vte_terminal_draw_cells(terminal,
+                                                       &item, 1,
+                                                       fore, back, FALSE,
+                                                       bold,
+                                                       underline,
+                                                       strikethrough,
+                                                       hilite,
+                                                       FALSE,
+                                                       x +
+                                                       ((i - column) * column_width),
+                                                       y,
+                                                       x_offs, y_offs,
+                                                       ascent, FALSE,
+                                                       column_width *
+                                                       item.columns,
+                                                       row_height,
+                                                       display,
+                                                       gdrawable, drawable,
+                                                       colormap,
+                                                       visual,
+                                                       ggc, gc,
+#ifdef HAVE_XFT
+                                                       ftdraw,
+#endif
+                                                       layout);
+                       }
                        i += item.columns;
                        continue;
                }
@@ -12938,9 +13257,6 @@ vte_terminal_draw_row(VteTerminal *terminal,
                                break;
                        }
                        /* Graphic characters must be drawn individually. */
-                       if ((cell != NULL) && (cell->alternate)) {
-                               break;
-                       }
                        if ((cell != NULL) && vte_unichar_isgraphic(cell->c)) {
                                break;
                        }
@@ -13045,6 +13361,7 @@ vte_terminal_paint(GtkWidget *widget, GdkRectangle *area)
        long width, height, ascent, descent, delta;
        int i, len, fore, back;
        gboolean blink, bold, underline, hilite, monospaced, strikethrough;
+       gboolean drawn;
 #ifdef HAVE_XFT
        XftDraw *ftdraw = NULL;
 #endif
@@ -13176,20 +13493,54 @@ vte_terminal_paint(GtkWidget *widget, GdkRectangle *area)
                                terminal->pvt->screen->reverse_mode;
                        vte_terminal_determine_colors(terminal, cell, blink,
                                                      &fore, &back);
-                       if ((cell != NULL) &&
-                           (cell->alternate || vte_unichar_isgraphic(cell->c))) {
-                               vte_terminal_draw_graphic(terminal,
-                                                         cell->c, fore, back,
-                                                         TRUE,
-                                                         col * width - x_offs,
-                                                         row * height - y_offs,
-                                                         terminal->char_width,
-                                                         terminal->char_height,
-                                                         display,
-                                                         gdrawable,
-                                                         drawable,
-                                                         ggc,
-                                                         gc);
+                       if ((cell != NULL) && vte_unichar_isgraphic(cell->c)) {
+                               item.c = cell->c;
+                               item.columns = cell->columns;
+                               drawn = vte_terminal_draw_graphic(terminal,
+                                                                 cell->c, fore, back,
+                                                                 TRUE,
+                                                                 col * width - x_offs,
+                                                                 row * height - y_offs,
+                                                                 terminal->char_width,
+                                                                 terminal->char_height,
+                                                                 display,
+                                                                 gdrawable,
+                                                                 drawable,
+                                                                 ggc,
+                                                                 gc);
+                               if (!drawn) {
+                                       item.xpad = vte_terminal_get_char_padding(terminal,
+                                                                                 display,
+                                                                                 item.c);
+                                       vte_terminal_draw_cells(terminal,
+                                                               &item, 1,
+                                                               fore, back,
+                                                               FALSE,
+                                                               cell->bold,
+                                                               cell->underline,
+                                                               cell->strikethrough,
+                                                               FALSE,
+                                                               FALSE,
+                                                               col *
+                                                               width - x_offs,
+                                                               row *
+                                                               height - y_offs,
+                                                               x_offs, y_offs,
+                                                               ascent, FALSE,
+                                                               width *
+                                                               cell->columns,
+                                                               height,
+                                                               display,
+                                                               gdrawable,
+                                                               drawable,
+                                                               colormap,
+                                                               visual,
+                                                               ggc, gc,
+#ifdef HAVE_XFT
+                                                               ftdraw,
+#endif
+                                                               layout);
+                               }
                        } else {
                                item.c = cell ? cell->c : ' ';
                                item.columns = cell ? cell->columns : 1;
@@ -13432,6 +13783,8 @@ vte_terminal_class_init(VteTerminalClass *klass, gconstpointer data)
 {
        GObjectClass *gobject_class;
        GtkWidgetClass *widget_class;
+       GQuark quark;
+       int i;
 
        bindtextdomain(PACKAGE, LOCALEDIR);
 
@@ -13665,13 +14018,23 @@ vte_terminal_class_init(VteTerminalClass *klass, gconstpointer data)
                             G_TYPE_NONE, 0);
 
        /* Try to determine some acceptable encoding names. */
-       if (_vte_table_narrow_encoding() == NULL) {
+       if (_vte_matcher_narrow_encoding() == NULL) {
                g_error("Don't know how to read ISO-8859-1 data!");
        }
-       if (_vte_table_wide_encoding() == NULL) {
+       if (_vte_matcher_wide_encoding() == NULL) {
                g_error("Don't know how to read native-endian unicode data!");
        }
 
+       /* Initialize the ambiguous codesets table. */
+       vte_ambiguous_wide_codeset_table = g_hash_table_new(g_direct_hash,
+                                                           g_direct_equal);
+       for (i = 0; i < G_N_ELEMENTS(vte_ambiguous_wide_codeset_list); i++) {
+               quark = g_quark_from_static_string(vte_ambiguous_wide_codeset_list[i]);
+               g_hash_table_insert(vte_ambiguous_wide_codeset_table,
+                                   GINT_TO_POINTER(quark),
+                                   GINT_TO_POINTER(quark));
+       }
+
 #ifdef VTE_DEBUG
        /* Turn on debugging if we were asked to. */
        if (getenv("VTE_DEBUG_FLAGS") != NULL) {
@@ -14615,7 +14978,7 @@ vte_terminal_set_word_chars(VteTerminal *terminal, const char *spec)
                return;
        }
        /* Convert the spec from UTF-8 to a string of gunichars . */
-       conv = g_iconv_open(_vte_table_wide_encoding(), "UTF-8");
+       conv = g_iconv_open(_vte_matcher_wide_encoding(), "UTF-8");
        if (conv == ((GIConv) -1)) {
                /* Aaargh.  We're screwed. */
                g_warning(_("g_iconv_open() failed setting word characters"));
index 361deb8..249172b 100644 (file)
--- a/src/vte.h
+++ b/src/vte.h
@@ -107,7 +107,7 @@ typedef enum {
 struct vte_char_attributes {
        long row, column;
        GdkColor fore, back;
-       gboolean underline:1, alternate:1, strikethrough:1;
+       gboolean underline:1, strikethrough:1;
 };
 
 /* The widget's type. */
index 1998306..49dfdf4 100644 (file)
--- a/vte.spec
+++ b/vte.spec
@@ -1,5 +1,5 @@
 Name: vte
-Version: 0.10.5
+Version: 0.10.6
 Release: 1
 Summary: An experimental terminal emulator.
 License: LGPL
@@ -37,10 +37,30 @@ rm -fr $RPM_BUILD_ROOT
 %install
 rm -fr $RPM_BUILD_ROOT
 make install DESTDIR=$RPM_BUILD_ROOT
-%find_lang %{name}
+
+# Remove the sample app.
 rm $RPM_BUILD_ROOT/%{_bindir}/%{name}
+
+# Remove the .la file.
 rm $RPM_BUILD_ROOT/%{_libdir}/lib%{name}.la
 
+# Work around AM_PATH_PYTHON from automake 1.6.3 not being multilib-aware.
+if test %{_libdir} != %{_prefix}/lib ; then
+       badpyexecdir=`ls -d $RPM_BUILD_ROOT/%{_prefix}/lib/python* 2> /dev/null`
+       if test -n "$badpyexecdir" ; then
+               pyexecdirver=`basename $badpyexecdir`
+               install -d -m755 $RPM_BUILD_ROOT/%{_libdir}/${pyexecdirver}
+               mv ${badpyexecdir}/site-packages $RPM_BUILD_ROOT/%{_libdir}/${pyexecdirver}/
+       fi
+fi
+
+# Remove static python modules and la files, which are probably useless to
+# Python anyway.
+rm -f $RPM_BUILD_ROOT/%{_libdir}/python*/site-packages/*.la
+rm -f $RPM_BUILD_ROOT/%{_libdir}/python*/site-packages/*.a
+
+%find_lang %{name}
+
 %post -p /sbin/ldconfig
 
 %postun -p /sbin/ldconfig
@@ -73,6 +93,12 @@ rm $RPM_BUILD_ROOT/%{_libdir}/lib%{name}.la
 %{_libdir}/pkgconfig/*
 
 %changelog
+* Mon Dec  9 2002 Nalin Dahyabhai <nalin@redhat.com> 0.10.6-1
+- handle ambiguous-width line-drawing characters
+
+* Mon Dec  9 2002 Nalin Dahyabhai <nalin@redhat.com> 0.10.5-2
+- work around AM_PATH_PYTHON not being multilib-aware
+
 * Tue Dec  3 2002 Nalin Dahyabhai <nalin@redhat.com> 0.10.5-1
 - cleaned up the keyboard