more $pkglibdir -> $libexecdir fixing. add rules for generating ps and
authorNalin Dahyabhai <nalin@src.gnome.org>
Mon, 14 Oct 2002 21:07:58 +0000 (21:07 +0000)
committerNalin Dahyabhai <nalin@src.gnome.org>
Mon, 14 Oct 2002 21:07:58 +0000 (21:07 +0000)
* configure.in: more $pkglibdir -> $libexecdir fixing.
* doc/Makefile.am: add rules for generating ps and text versions of the ctlseqs
docs.
* doc/reference/tmpl/vte.sgml: add snippet for "commit".
* python/python/vte.defs: update to add a binding for
vte_terminal_fork_logged_command().
* src/buffer.h: add a warning comment that these are private interfaces.  Wrap
declarations in G_BEGIN_DECLS/G_END_DECLS.
* src/caps.h: add macros for the SS2/SS3 sequences.
* src/marshal.list: add a marshaller for the "commit" signal.
* src/keymap.c, src/keymap.h: move the getting-more-convoluted keypress-handling
code to a shell that parses tables of static info.
* src/pty.c: reset signal handlers before exec() (Red Hat #75341)
* src/vte.c: use the keymap for most non-printable keys.  Add a "commit" signal
to allow an app to just use the terminal for displaying data and
grabbing input.  Obey the application's desired meta-sends-escape
setting.  Recognize HP function key mode.  Recognize and handle legacy
XTerm function key mode.  Force a redraw if the child application tries
to switch to 80/132 columns, even though we don't usually let them try.
Don't try to send keystrokes to the child pty when there is no child
pty.  Don't convert final whitespace to newlines when copying text
(Red Hat #74611).  Properly distinguish cursor key mode and keypad key
mode, obey application mode for cursor keys,
* python/cat.py: test program for running without a command.
* termcaps/xterm: change the definitions for ku/kd/kl/kr to match XTerm in
normal cursor mode instead of application cursor mode.

17 files changed:
ChangeLog
configure.in
doc/Makefile.am
doc/reference/tmpl/vte.sgml
python/cat.py [new file with mode: 0755]
python/vte.defs
src/Makefile.am
src/buffer.h
src/caps.h
src/keymap.c [new file with mode: 0644]
src/keymap.h [new file with mode: 0644]
src/marshal.list
src/pty.c
src/vte.c
src/vte.h
src/vteapp.c
termcaps/xterm

index 92f4bc2..2cbb63d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2002-10-14 nalin
+       * configure.in: more $pkglibdir -> $libexecdir fixing.
+       * doc/Makefile.am: add rules for generating ps and text versions of the
+       ctlseqs docs.
+       * doc/reference/tmpl/vte.sgml: add snippet for "commit".
+       * python/python/vte.defs: update to add a binding for
+       vte_terminal_fork_logged_command().
+       * src/buffer.h: add a warning comment that these are private interfaces.
+       Wrap declarations in G_BEGIN_DECLS/G_END_DECLS.
+       * src/caps.h: add macros for the SS2/SS3 sequences.
+       * src/marshal.list: add a marshaller for the "commit" signal.
+       * src/keymap.c, src/keymap.h: move the getting-more-convoluted
+       keypress-handling code to a shell that parses tables of static info.
+       * src/vte.c: use the keymap for most non-printable keys.  Add a "commit"
+       signal to allow an app to just use the terminal for displaying data and
+       grabbing input.  Obey the application's desired meta-sends-escape
+       setting.  Recognize HP function key mode.  Recognize and handle
+       legacy XTerm function key mode.  Force a redraw if the child application
+       tries to switch to 80/132 columns, even though we don't usually let
+       them try.  Don't try to send keystrokes to the child pty when there
+       is no child pty.  Don't convert final whitespace to newlines when
+       copying text (Red Hat #74611).
+       * python/cat.py: test program for running without a command.
+       * termcaps/xterm: change the definitions for ku/kd/kl/kr to match
+       XTerm in normal cursor mode instead of application cursor mode.
+
+2002-10-11 nalin
+       * src/vte.c: properly distinguish cursor key mode and keypad key mode,
+       obey application mode for cursor keys,
+       * src/pty.c: reset signal handlers before exec() (Red Hat #75341)
+
 2002-10-11 nalin
        * src/trie.c: change the typedef of wint_t here to match vte.c (now
        a gunichar instead of a long).  Spotted by Brian Cameron.
index 06aa76a..dcad072 100644 (file)
@@ -161,7 +161,9 @@ fi
 if test x$prefix = xNONE ; then
        mydatadir=`echo $mydatadir | sed s,NONE,$ac_default_prefix,g`
 fi
-AC_DEFINE_UNQUOTED(LIBEXECDIR,"$mylibdir/$PACKAGE",
+AC_DEFINE_UNQUOTED(PKGLIBDIR,"$mylibdir/$PACKAGE",
+                   [The location where package-specific helpers can be found.])
+AC_DEFINE_UNQUOTED(LIBEXECDIR,"$mylibexecdir",
                    [The location where package-specific helpers can be found.])
 AC_DEFINE_UNQUOTED(DATADIR,"$mydatadir",
                    [The location where arch-independent package-specific data can be found.])
index f3ddc22..a710e69 100644 (file)
@@ -1 +1,7 @@
 SUBDIRS = reference
+
+ctlseqs.ps: ctlseqs.ms
+       tbl $^ | groff -ms > $@
+
+ctlseqs.txt: ctlseqs.ms
+       tbl $^ | nroff -c -ms > $@
index 98c54ce..55edb46 100644 (file)
@@ -630,6 +630,17 @@ vte_terminal_fork_command() has exited.
 
 @vteterminal: the object which received the signal.
 
+<!-- ##### SIGNAL VteTerminal::commit ##### -->
+<para>
+Emitted whenever the terminal receives input from the user and prepares to send
+it to the child process.  The signal is emitted even when there is no child
+process.
+</para>
+
+@vteterminal: the object which received the signal.
+@arg1: a string of text.
+@arg2: the length of that string of text.
+
 <!-- ##### SIGNAL VteTerminal::contents-changed ##### -->
 <para>
 Emitted whenever the visible appearance of the terminal has changed.  Used
diff --git a/python/cat.py b/python/cat.py
new file mode 100755 (executable)
index 0000000..5d12393
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/python2.2
+import sys
+import string
+import getopt
+import gtk
+import vte
+
+def main_quit(object, *args):
+       gtk.main_quit()
+
+def commit_cb(object, *args):
+       (text, length) = args
+       sys.stdout.write(text)
+       sys.stdout.flush()
+       object.feed(text, length)
+
+if __name__ == '__main__':
+       font = "fixed 12"
+       scrollback = 100
+       # Let the user override them.
+       (shorts, longs) = getopt.getopt(sys.argv[1:], "f:", ["font="])
+       for argpair in (shorts + longs):
+               if ((argpair[0] == '-f') or (argpair[0] == '--font')):
+                       print "Setting font to `" + argpair[1] + "'."
+                       font = argpair[1]
+       window = gtk.Window()
+       window.connect("delete-event", main_quit)
+
+       terminal = vte.Terminal()
+       terminal.set_cursor_blinks(gtk.TRUE)
+       terminal.set_emulation("xterm")
+       terminal.set_font_from_string(font)
+       terminal.set_scrollback_lines(1000)
+       terminal.set_audible_bell(gtk.TRUE)
+       terminal.set_visible_bell(gtk.FALSE)
+       terminal.connect("commit", commit_cb)
+       terminal.show()
+
+       scrollbar = gtk.VScrollbar()
+       scrollbar.set_adjustment(terminal.get_adjustment())
+
+       box = gtk.HBox()
+       box.pack_start(terminal)
+       box.pack_start(scrollbar)
+
+       window.add(box)
+       window.show_all()
+       gtk.main()
index 41960c8..ec93278 100644 (file)
   )
 )
 
+(define-method fork_logged_command
+  (of-object "VteTerminal")
+  (c-name "vte_terminal_fork_logged_command")
+  (return-type "pid_t")
+  (parameters
+    '("const-char*" "command")
+    '("char**" "argv")
+    '("char**" "envv")
+    '("gboolean" "lastlog")
+    '("gboolean" "utmp")
+    '("gboolean" "wtmp")
+  )
+)
+
 (define-method feed
   (of-object "VteTerminal")
   (c-name "vte_terminal_feed")
index 70bc49f..1e4100e 100644 (file)
@@ -24,6 +24,8 @@ libvte_la_SOURCES = \
        debug.h \
        iso2022.c \
        iso2022.h \
+       keymap.c \
+       keymap.h \
        marshal.c \
        marshal.h \
        pty.c \
index 92a7107..3252650 100644 (file)
  *
  */
 
-#ifndef buffer_h
-#define buffer_h
+/* The interfaces in this file are subject to change at any time. */
+
+#ifndef vte_buffer_h_included
+#define vte_buffer_h_included
 
 #include <sys/types.h>
 
+G_BEGIN_DECLS
+
 struct _vte_buffer {
        /* public */
        unsigned char *bytes;
@@ -40,4 +44,6 @@ void _vte_buffer_consume(struct _vte_buffer *buffer, size_t length);
 void _vte_buffer_clear(struct _vte_buffer *buffer);
 void _vte_buffer_set_minimum_size(struct _vte_buffer *buffer, size_t length);
 
+G_END_DECLS
+
 #endif
index 28f0626..f1fc7e7 100644 (file)
@@ -33,6 +33,8 @@ G_BEGIN_DECLS
 #define _VTE_CAP_OSC _VTE_CAP_ESC "]"  /* Operating System Command */
 #define _VTE_CAP_PM  _VTE_CAP_ESC "^"  /* Privacy Message */
 #define _VTE_CAP_APC _VTE_CAP_ESC "_"  /* Application Program Command */
+#define _VTE_CAP_SS2 _VTE_CAP_ESC "N"  /* Single-shift to G2 */
+#define _VTE_CAP_SS3 _VTE_CAP_ESC "O"  /* Single-shift to G3 */
 
 /* A NULL-terminated list of capability strings which have string values,
  * which means they're either key sequences or commands. */
diff --git a/src/keymap.c b/src/keymap.c
new file mode 100644 (file)
index 0000000..59038fa
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) 2002 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ident "$Id$"
+#include "../config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include "caps.h"
+#include "keymap.h"
+
+enum _vte_cursor_mode {
+       cursor_normal = 1 << 0,
+       cursor_app =    1 << 1,
+};
+
+enum _vte_keypad_mode {
+       keypad_normal = 1 << 0,
+       keypad_app =    1 << 1,
+       keypad_vt220 =  1 << 2,
+};
+
+enum _vte_fkey_mode {
+       fkey_normal =   1 << 0,
+       fkey_sun =      1 << 1,
+       fkey_hp =       1 << 2,
+       fkey_legacy =   1 << 3,
+};
+
+#define cursor_all     (cursor_normal | cursor_app)
+#define keypad_all     (keypad_normal | keypad_app | keypad_vt220)
+#define fkey_all       (fkey_normal | fkey_sun | fkey_hp | fkey_legacy)
+
+struct _vte_keymap_entry {
+       enum _vte_cursor_mode cursor_mode;
+       enum _vte_keypad_mode keypad_mode;
+       enum _vte_fkey_mode fkey_mode;
+       GdkModifierType mod_mask;
+       const char *normal;
+       ssize_t normal_length;
+       const char *special;
+};
+
+/* Normal keys unaffected by modes. */
+static struct _vte_keymap_entry _vte_keymap_GDK_space[] = {
+       /* Control+space = NUL */
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, "", 1, NULL},
+       /* Regular space. */
+       {cursor_all, keypad_all, fkey_all, 0, " ", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_Tab[] = {
+       /* Shift+Tab = BackTab */
+       {cursor_all, keypad_all, fkey_all, GDK_SHIFT_MASK, NULL, 1, "kB"},
+       /* Regular tab. */
+       {cursor_all, keypad_all, fkey_all, 0, "\t", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_Insert[] = {
+       {cursor_all, keypad_app, fkey_all, 0, NULL, 0, "kI"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_ISO_Left_Tab[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 1, "kB"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_Home[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "kh"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_End[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "@7"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+/* Keys affected by the cursor key mode. */
+static struct _vte_keymap_entry _vte_keymap_GDK_Up[] = {
+       {cursor_normal, keypad_all, fkey_all, 0, NULL, 0, "ku"},
+       {cursor_app, keypad_all, fkey_all, 0, _VTE_CAP_SS3 "A", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_Down[] = {
+       {cursor_normal, keypad_all, fkey_all, 0, NULL, 0, "kd"},
+       {cursor_app, keypad_all, fkey_all, 0, _VTE_CAP_SS3 "B", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_Right[] = {
+       {cursor_normal, keypad_all, fkey_all, 0, NULL, 0, "kr"},
+       {cursor_app, keypad_all, fkey_all, 0, _VTE_CAP_SS3 "C", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_Left[] = {
+       {cursor_normal, keypad_all, fkey_all, 0, NULL, 0, "kl"},
+       {cursor_app, keypad_all, fkey_all, 0, _VTE_CAP_SS3 "D", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+/* Keys (potentially) affected by the keypad key mode. */
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Space[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, " ", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 " ", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 " ", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Tab[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, "\t", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "I", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "I", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Enter[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "@8"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "M", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "M", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_F1[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k1"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_F2[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k2"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_F3[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k3"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_F4[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k4"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Multiply[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, "*", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "j", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Add[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, "+", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "k", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Separator[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, ",", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "l", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Subtract[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, "-", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "m", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Decimal_Delete[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, ".", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "3~", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Divide[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, "/", 1, NULL},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_SS3 "o", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+/* GDK already separates keypad "0" from keypad "Insert", so the only time
+ * we'll see this key is when NumLock is on, and that means that we're in
+ * "normal" mode. */
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_0[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "0", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_1[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "1", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_2[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "2", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_3[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "3", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_4[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "4", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_5[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "5", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_6[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "6", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_7[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "7", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_8[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "8", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_9[] = {
+       {cursor_all, keypad_all, fkey_all, 0, "9", 1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+/* These are the same keys as above, but without numlock.  If there's a
+ * capability associated with the key, then we send that, unless we're in
+ * application mode. */
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Insert[] = {
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "2~", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "p", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_End[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "K4"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "4~", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "q", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Down[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "kd"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "B", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "r", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Page_Down[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "K5"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "5~", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "s", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Left[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "kl"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "D", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "t", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Begin[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "K2"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "E", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "u", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Right[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "kr"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "C", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "v", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Home[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "K1"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "1~", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "w", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Up[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "ku"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "A", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "x", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_KP_Page_Up[] = {
+       {cursor_all, keypad_normal, fkey_all, 0, NULL, 0, "K3"},
+       {cursor_all, keypad_app, fkey_all, 0, _VTE_CAP_CSI "5~", -1, NULL},
+       {cursor_all, keypad_vt220, fkey_all, 0, _VTE_CAP_SS3 "y", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+
+/* Keys affected by the function key mode. */
+static struct _vte_keymap_entry _vte_keymap_GDK_F1[] = {
+       {cursor_all, keypad_all, fkey_legacy, 0, _VTE_CAP_CSI "11~", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F3"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k1"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F2[] = {
+       {cursor_all, keypad_all, fkey_legacy, 0, _VTE_CAP_CSI "12~", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F4"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k2"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F3[] = {
+       {cursor_all, keypad_all, fkey_legacy, 0, _VTE_CAP_CSI "13~", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F5"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k3"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F4[] = {
+       {cursor_all, keypad_all, fkey_legacy, 0, _VTE_CAP_CSI "14~", -1, NULL},
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F6"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k4"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F5[] = {
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F7"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k5"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F6[] = {
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F8"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k6"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F7[] = {
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "F9"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k7"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F8[] = {
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "FA"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k8"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F9[] = {
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "FB"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k9"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F10[] = {
+       {cursor_all, keypad_all, fkey_all, GDK_CONTROL_MASK, NULL, 0, "FC"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "k;"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F11[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F1"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F12[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F2"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F13[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F3"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F14[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F4"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F15[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F5"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F16[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F6"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F17[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F7"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F18[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F8"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F19[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "F9"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F20[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FA"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F21[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FB"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F22[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FC"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F23[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FD"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F24[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FE"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F25[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FF"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F26[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FG"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F27[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FH"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F28[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FI"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F29[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FJ"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F30[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FK"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F31[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FL"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F32[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FM"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F33[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FN"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F34[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FO"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_entry _vte_keymap_GDK_F35[] = {
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, "FP"},
+       {cursor_all, keypad_all, fkey_all, 0, NULL, 0, NULL},
+};
+
+static struct _vte_keymap_group {
+       guint keyval;
+       struct _vte_keymap_entry *entries;
+} _vte_keymap[] = {
+       {GDK_space,             _vte_keymap_GDK_space},
+       {GDK_Tab,               _vte_keymap_GDK_Tab},
+       {GDK_ISO_Left_Tab,      _vte_keymap_GDK_ISO_Left_Tab},
+       {GDK_Home,              _vte_keymap_GDK_Home},
+       {GDK_End,               _vte_keymap_GDK_End},
+       {GDK_Insert,            _vte_keymap_GDK_Insert},
+
+       {GDK_Up,                _vte_keymap_GDK_Up},
+       {GDK_Down,              _vte_keymap_GDK_Down},
+       {GDK_Right,             _vte_keymap_GDK_Right},
+       {GDK_Left,              _vte_keymap_GDK_Left},
+
+       {GDK_KP_Space,          _vte_keymap_GDK_KP_Space},
+       {GDK_KP_Tab,            _vte_keymap_GDK_KP_Tab},
+       {GDK_KP_Enter,          _vte_keymap_GDK_KP_Enter},
+       {GDK_KP_F1,             _vte_keymap_GDK_KP_F1},
+       {GDK_KP_F2,             _vte_keymap_GDK_KP_F2},
+       {GDK_KP_F3,             _vte_keymap_GDK_KP_F3},
+       {GDK_KP_F4,             _vte_keymap_GDK_KP_F4},
+       {GDK_KP_Multiply,       _vte_keymap_GDK_KP_Multiply},
+       {GDK_KP_Add,            _vte_keymap_GDK_KP_Add},
+       {GDK_KP_Separator,      _vte_keymap_GDK_KP_Separator},
+       {GDK_KP_Subtract,       _vte_keymap_GDK_KP_Subtract},
+       {GDK_KP_Decimal,        _vte_keymap_GDK_KP_Decimal_Delete},
+       {GDK_KP_Delete,         _vte_keymap_GDK_KP_Decimal_Delete},
+       {GDK_KP_Divide,         _vte_keymap_GDK_KP_Divide},
+       {GDK_KP_0,              _vte_keymap_GDK_KP_0},
+       {GDK_KP_Insert,         _vte_keymap_GDK_KP_Insert},
+       {GDK_KP_1,              _vte_keymap_GDK_KP_1},
+       {GDK_KP_End,            _vte_keymap_GDK_KP_End},
+       {GDK_KP_2,              _vte_keymap_GDK_KP_2},
+       {GDK_KP_Down,           _vte_keymap_GDK_KP_Down},
+       {GDK_KP_3,              _vte_keymap_GDK_KP_3},
+       {GDK_KP_Page_Down,      _vte_keymap_GDK_KP_Page_Down},
+       {GDK_KP_4,              _vte_keymap_GDK_KP_4},
+       {GDK_KP_Left,           _vte_keymap_GDK_KP_Left},
+       {GDK_KP_5,              _vte_keymap_GDK_KP_5},
+       {GDK_KP_Begin,          _vte_keymap_GDK_KP_Begin},
+       {GDK_KP_6,              _vte_keymap_GDK_KP_6},
+       {GDK_KP_Right,          _vte_keymap_GDK_KP_Right},
+       {GDK_KP_7,              _vte_keymap_GDK_KP_7},
+       {GDK_KP_Home,           _vte_keymap_GDK_KP_Home},
+       {GDK_KP_8,              _vte_keymap_GDK_KP_8},
+       {GDK_KP_Up,             _vte_keymap_GDK_KP_Up},
+       {GDK_KP_9,              _vte_keymap_GDK_KP_9},
+       {GDK_KP_Page_Up,        _vte_keymap_GDK_KP_Page_Up},
+
+       {GDK_F1,                _vte_keymap_GDK_F1},
+       {GDK_F2,                _vte_keymap_GDK_F2},
+       {GDK_F3,                _vte_keymap_GDK_F3},
+       {GDK_F4,                _vte_keymap_GDK_F4},
+       {GDK_F5,                _vte_keymap_GDK_F5},
+       {GDK_F6,                _vte_keymap_GDK_F6},
+       {GDK_F7,                _vte_keymap_GDK_F7},
+       {GDK_F8,                _vte_keymap_GDK_F8},
+       {GDK_F9,                _vte_keymap_GDK_F9},
+       {GDK_F10,               _vte_keymap_GDK_F10},
+       {GDK_F11,               _vte_keymap_GDK_F11},
+       {GDK_F12,               _vte_keymap_GDK_F12},
+       {GDK_F13,               _vte_keymap_GDK_F13},
+       {GDK_F14,               _vte_keymap_GDK_F14},
+       {GDK_F15,               _vte_keymap_GDK_F15},
+       {GDK_F16,               _vte_keymap_GDK_F16},
+       {GDK_F17,               _vte_keymap_GDK_F17},
+       {GDK_F18,               _vte_keymap_GDK_F18},
+       {GDK_F19,               _vte_keymap_GDK_F19},
+       {GDK_F20,               _vte_keymap_GDK_F20},
+       {GDK_F21,               _vte_keymap_GDK_F21},
+       {GDK_F22,               _vte_keymap_GDK_F22},
+       {GDK_F23,               _vte_keymap_GDK_F23},
+       {GDK_F24,               _vte_keymap_GDK_F24},
+       {GDK_F25,               _vte_keymap_GDK_F25},
+       {GDK_F26,               _vte_keymap_GDK_F26},
+       {GDK_F27,               _vte_keymap_GDK_F27},
+       {GDK_F28,               _vte_keymap_GDK_F28},
+       {GDK_F29,               _vte_keymap_GDK_F29},
+       {GDK_F30,               _vte_keymap_GDK_F30},
+       {GDK_F31,               _vte_keymap_GDK_F31},
+       {GDK_F32,               _vte_keymap_GDK_F32},
+       {GDK_F33,               _vte_keymap_GDK_F33},
+       {GDK_F34,               _vte_keymap_GDK_F34},
+       {GDK_F35,               _vte_keymap_GDK_F35},
+};
+
+/* Map the specified keyval/modifier setup, dependent on the mode, to either
+ * a literal string or a capability name. */
+void
+_vte_keymap_map(guint keyval,
+               GdkModifierType modifiers,
+               gboolean sun_mode,
+               gboolean hp_mode,
+               gboolean legacy_mode,
+               gboolean vt220_mode,
+               gboolean app_cursor_keys,
+               gboolean app_keypad_keys,
+               char **normal,
+               size_t *normal_length,
+               const char **special)
+{
+       int i, modifier_value;
+       gboolean fkey;
+       struct _vte_keymap_entry *entries;
+       enum _vte_cursor_mode cursor_mode;
+       enum _vte_keypad_mode keypad_mode;
+       enum _vte_fkey_mode fkey_mode;
+
+       g_return_if_fail(normal != NULL);
+       g_return_if_fail(normal_length != NULL);
+       g_return_if_fail(special != NULL);
+
+       /* Start from scratch. */
+       *normal = NULL;
+       *special = NULL;
+       *normal_length = 0;
+
+       /* Search for the list for this key. */
+       entries = NULL;
+       fkey = FALSE;
+       for (i = 0; i < G_N_ELEMENTS(_vte_keymap); i++) {
+#ifdef VTE_DEBUG
+               int j;
+               entries = _vte_keymap[i].entries;
+               for (j = 0; entries[j].normal || entries[j].special; j++) {
+                       if (entries[j].normal != NULL) {
+                               g_assert(entries[j].normal_length != 0);
+                       }
+               }
+               entries = NULL;
+#endif
+               if (_vte_keymap[i].keyval == GDK_F1) {
+                       /* Every entry after this point is a function key. */
+                       fkey = TRUE;
+               }
+               if (_vte_keymap[i].keyval == keyval) {
+                       /* Found it! */
+                       entries = _vte_keymap[i].entries;
+                       break;
+               }
+       }
+       if (entries == NULL) {
+               return;
+       }
+
+       /* Build mode masks.  Numlock negates application cursor mode. */
+       if (modifiers & VTE_NUMLOCK_MASK) {
+               cursor_mode = cursor_normal;
+       } else {
+               cursor_mode = app_cursor_keys ? cursor_app : cursor_normal;
+       }
+       keypad_mode = app_keypad_keys ?
+                     (vt220_mode ?  keypad_vt220 : keypad_app) :
+                     keypad_normal;
+       if (sun_mode) {
+               fkey_mode = fkey_sun;
+       } else
+       if (hp_mode) {
+               fkey_mode = fkey_hp;
+       } else
+       if (legacy_mode) {
+               fkey_mode = fkey_legacy;
+       } else {
+               fkey_mode = fkey_normal;
+       }
+       modifiers &= (GDK_SHIFT_MASK | GDK_CONTROL_MASK | VTE_META_MASK);
+
+       /* Search for the conditions. */
+       for (i = 0; entries[i].normal || entries[i].special; i++)
+       if ((entries[i].cursor_mode & cursor_mode) &&
+           (entries[i].keypad_mode & keypad_mode) &&
+           (entries[i].fkey_mode & fkey_mode))
+       if ((modifiers & entries[i].mod_mask) == entries[i].mod_mask) {
+               if (entries[i].normal) {
+                       if (entries[i].normal_length != -1) {
+                               *normal_length = entries[i].normal_length;
+                       } else {
+                               *normal_length = strlen(entries[i].normal);
+                       }
+                       /* Return a copy of the normal string. */
+                       if (fkey && (fkey_mode == fkey_sun)) {
+                               /* Append the modifier state. */
+                               modifier_value = 0;
+                               switch (modifiers) {
+                               case GDK_SHIFT_MASK:
+                                       modifier_value = 2;
+                                       break;
+                               case VTE_META_MASK:
+                                       modifier_value = 3;
+                                       break;
+                               case GDK_SHIFT_MASK | VTE_META_MASK:
+                                       modifier_value = 4;
+                                       break;
+                               case GDK_CONTROL_MASK:
+                                       modifier_value = 5;
+                                       break;
+                               case GDK_CONTROL_MASK | GDK_SHIFT_MASK:
+                                       modifier_value = 6;
+                                       break;
+                               case GDK_CONTROL_MASK | VTE_META_MASK:
+                                       modifier_value = 7;
+                                       break;
+                               case GDK_CONTROL_MASK | GDK_SHIFT_MASK |
+                                    VTE_META_MASK:
+                                       modifier_value = 8;
+                                       break;
+                               default:
+                                       modifier_value = 8;
+                                       break;
+                               }
+                               if (modifier_value == 0) {
+                                       /* Copy it verbatim. */
+                                       *normal = g_memdup(entries[i].normal,
+                                                          *normal_length + 1);
+                               } else {
+                                       /* Copy and stuff in the modifiers. */
+                                       *normal = g_malloc0(*normal_length + 3);
+                                       memcpy(*normal, entries[i].normal,
+                                              entries[i].normal_length);
+                                       (*normal)[entries[i].normal_length + 1] = (*normal)[entries[i].normal_length - 1];
+                                       (*normal)[entries[i].normal_length] = '0' + modifier_value;
+                                       (*normal)[entries[i].normal_length - 1] = ';';
+                               }
+                       } else {
+                               /* Copy it verbatim. */
+                               *normal = g_memdup(entries[i].normal,
+                                                  *normal_length + 1);
+                       }
+                       return;
+               }
+               if (entries[i].special) {
+                       /* Return the original special string. */
+                       *special = entries[i].special;
+                       return;
+               }
+       }
+}
+
+gboolean
+_vte_keymap_key_is_modifier(guint keyval)
+{
+       gboolean modifier = FALSE;
+       /* Determine if this is just a modifier key. */
+       switch (keyval) {
+       case GDK_Alt_L:
+       case GDK_Alt_R:
+       case GDK_Caps_Lock:
+       case GDK_Control_L:
+       case GDK_Control_R:
+       case GDK_Eisu_Shift:
+       case GDK_Hyper_L:
+       case GDK_Hyper_R:
+       case GDK_ISO_First_Group_Lock:
+       case GDK_ISO_Group_Lock:
+       case GDK_ISO_Group_Shift:
+       case GDK_ISO_Last_Group_Lock:
+       case GDK_ISO_Level3_Lock:
+       case GDK_ISO_Level3_Shift:
+       case GDK_ISO_Lock:
+       case GDK_ISO_Next_Group_Lock:
+       case GDK_ISO_Prev_Group_Lock:
+       case GDK_Kana_Lock:
+       case GDK_Kana_Shift:
+       case GDK_Meta_L:
+       case GDK_Meta_R:
+       case GDK_Num_Lock:
+       case GDK_Scroll_Lock:
+       case GDK_Shift_L:
+       case GDK_Shift_Lock:
+       case GDK_Shift_R:
+       case GDK_Super_L:
+       case GDK_Super_R:
+               modifier = TRUE;
+               break;
+       default:
+               modifier = FALSE;
+               break;
+       }
+       return modifier;
+}
diff --git a/src/keymap.h b/src/keymap.h
new file mode 100644 (file)
index 0000000..9e3763f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2002 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* The interfaces in this file are subject to change at any time. */
+
+#ifndef vte_keymap_h_included
+#define vte_keymap_h_included
+
+#ident "$Id$"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#define VTE_NUMLOCK_MASK               GDK_MOD2_MASK
+#define VTE_META_MASK                  GDK_MOD1_MASK
+
+G_BEGIN_DECLS
+
+/* Map the specified keyval/modifier setup, dependent on the mode, to either
+ * a literal string or a capability name. */
+void _vte_keymap_map(guint keyval,
+                    GdkModifierType modifiers,
+                    gboolean sun_mode,
+                    gboolean hp_mode,
+                    gboolean legacy_mode,
+                    gboolean vt220_mode,
+                    gboolean app_cursor_keys,
+                    gboolean app_keypad_keys,
+                    char **normal,
+                    size_t *normal_length,
+                    const char **special);
+/* Return TRUE if a keyval is just a modifier key */
+gboolean _vte_keymap_key_is_modifier(guint keyval);
+
+G_END_DECLS
+
+#endif
index 10e22d5..6f0c62c 100644 (file)
@@ -1,5 +1,6 @@
 VOID:VOID
 VOID:STRING
+VOID:STRING,UINT
 VOID:INT,INT
 VOID:UINT,UINT
 VOID:OBJECT,OBJECT
index aa8b274..4812e2f 100644 (file)
--- a/src/pty.c
+++ b/src/pty.c
@@ -64,6 +64,86 @@ static pid_t _vte_pty_helper_pid = -1;
 static int _vte_pty_helper_tunnel = -1;
 static GTree *_vte_pty_helper_map = NULL;
 
+/* Reset the handlers for all known signals to their defaults.  The parent
+ * (or one of the libraries it links to) may have changed one to be ignored. */
+static void
+_vte_pty_reset_signal_handlers(void)
+{
+       signal(SIGHUP,  SIG_DFL);
+       signal(SIGINT,  SIG_DFL);
+       signal(SIGILL,  SIG_DFL);
+       signal(SIGABRT, SIG_DFL);
+       signal(SIGFPE,  SIG_DFL);
+       signal(SIGKILL, SIG_DFL);
+       signal(SIGSEGV, SIG_DFL);
+       signal(SIGPIPE, SIG_DFL);
+       signal(SIGALRM, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGCONT, SIG_DFL);
+       signal(SIGSTOP, SIG_DFL);
+       signal(SIGTSTP, SIG_DFL);
+       signal(SIGTTIN, SIG_DFL);
+       signal(SIGTTOU, SIG_DFL);
+#ifdef SIGBUS
+       signal(SIGBUS,  SIG_DFL);
+#endif
+#ifdef SIGPOLL
+       signal(SIGPOLL, SIG_DFL);
+#endif
+#ifdef SIGPROF
+       signal(SIGPROF, SIG_DFL);
+#endif
+#ifdef SIGSYS
+       signal(SIGSYS,  SIG_DFL);
+#endif
+#ifdef SIGTRAP
+       signal(SIGTRAP, SIG_DFL);
+#endif
+#ifdef SIGURG
+       signal(SIGURG,  SIG_DFL);
+#endif
+#ifdef SIGVTALARM
+       signal(SIGVTALARM, SIG_DFL);
+#endif
+#ifdef SIGXCPU
+       signal(SIGXCPU, SIG_DFL);
+#endif
+#ifdef SIGXFSZ
+       signal(SIGXFSZ, SIG_DFL);
+#endif
+#ifdef SIGIOT
+       signal(SIGIOT,  SIG_DFL);
+#endif
+#ifdef SIGEMT
+       signal(SIGEMT,  SIG_DFL);
+#endif
+#ifdef SIGSTKFLT
+       signal(SIGSTKFLT, SIG_DFL);
+#endif
+#ifdef SIGIO
+       signal(SIGIO,   SIG_DFL);
+#endif
+#ifdef SIGCLD
+       signal(SIGCLD,  SIG_DFL);
+#endif
+#ifdef SIGPWR
+       signal(SIGPWR,  SIG_DFL);
+#endif
+#ifdef SIGINFO
+       signal(SIGINFO, SIG_DFL);
+#endif
+#ifdef SIGLOST
+       signal(SIGLOST, SIG_DFL);
+#endif
+#ifdef SIGWINCH
+       signal(SIGWINCH, SIG_DFL);
+#endif
+#ifdef SIGUNUSED
+       signal(SIGUNUSED, SIG_DFL);
+#endif
+}
+
 /* Run the given command, using the given descriptor as the controlling
  * terminal. */
 static int
@@ -122,6 +202,10 @@ _vte_pty_run_on_pty(int fd, char **env_add, const char *command, char **argv)
 #endif
        }
 
+       /* Reset our signals -- our parent may have done any number of
+        * weird things to them. */
+       _vte_pty_reset_signal_handlers();
+
        /* Outta here. */
        if (argv != NULL) {
                for (i = 0; (argv[i] != NULL); i++) ;
index 158fe06..56c5071 100644 (file)
--- a/src/vte.c
+++ b/src/vte.c
@@ -49,6 +49,7 @@
 #include "caps.h"
 #include "debug.h"
 #include "iso2022.h"
+#include "keymap.h"
 #include "marshal.h"
 #include "pty.h"
 #include "reaper.h"
@@ -144,19 +145,12 @@ struct vte_draw_item {
        guint16 xpad;
 };
 
-/* The terminal's keypad state.  A terminal can either be using the normal
- * keypad, or the "application" keypad.  Arrow key sequences, for example,
- * are really only defined for "application" mode. */
-typedef enum _VteKeypad {
-       VTE_KEYPAD_NORMAL,
-       VTE_KEYPAD_APPLICATION
-} VteKeypad;
-
-/* The terminal's function key setting. */
-typedef enum _VteFKey {
-       VTE_FKEY_VT220,
-       VTE_FKEY_SUNPC
-} VteFKey;
+/* The terminal's keypad/cursor state.  A terminal can either be using the
+ * normal keypad, or the "application" keypad. */
+typedef enum _VteKeymode {
+       VTE_KEYMODE_NORMAL,
+       VTE_KEYMODE_APPLICATION
+} VteKeymode;
 
 typedef struct _VteScreen VteScreen;
 
@@ -178,8 +172,12 @@ struct _VteTerminalPrivate {
                gboolean bw;
                gboolean ul;
        } flags;
-       int keypad;                     /* this would be a VteKeypad, but we
+       int keypad_mode, cursor_mode;   /* these would be VteKeymodes, but we
                                           need to guarantee its type */
+       gboolean sun_fkey_mode;
+       gboolean hp_fkey_mode;
+       gboolean legacy_fkey_mode;
+       gboolean vt220_fkey_mode;
        int fkey;                       /* this would be a VteFKey, but we
                                           need to guarantee its type */
        GHashTable *dec_saved;
@@ -260,7 +258,7 @@ struct _VteTerminalPrivate {
 
        /* Miscellaneous options. */
        VteTerminalEraseBinding backspace_binding, delete_binding;
-       gboolean alt_sends_escape;
+       gboolean meta_sends_escape;
        gboolean audible_bell;
        gboolean visible_bell;
        gboolean xterm_font_tweak;
@@ -801,6 +799,18 @@ vte_terminal_emit_selection_changed(VteTerminal *terminal)
        g_signal_emit_by_name(terminal, "selection-changed");
 }
 
+/* Emit a "commit" signal. */
+static void
+vte_terminal_emit_commit(VteTerminal *terminal, gchar *text, guint length)
+{
+#ifdef VTE_DEBUG
+       if (_vte_debug_on(VTE_DEBUG_SIGNALS)) {
+               fprintf(stderr, "Emitting `commit'.\n");
+       }
+#endif
+       g_signal_emit_by_name(terminal, "commit", text, length);
+}
+
 /* Emit an "emulation-changed" signal. */
 static void
 vte_terminal_emit_emulation_changed(VteTerminal *terminal)
@@ -1637,23 +1647,16 @@ vte_remove_line_internal(VteTerminal *terminal, glong position)
 
 /* Append a single item to a GArray a given number of times. */
 static void
-vte_g_array_append(GArray *array, gpointer array_end,
-                  gpointer item, guint count)
+vte_g_array_fill(GArray *array, gpointer item, guint final_size)
 {
-       long goal, add, added;
-       if (count == 0) {
+       if (array->len >= final_size) {
                return;
        }
-       goal = array->len + count;
-
-       g_array_append_val(array, item);
-       added = 1;
-       count--;
+       g_assert(array != NULL);
+       g_assert(item != NULL);
 
-       while (array->len < goal) {
-               add = MIN(added, goal - array->len);
-               g_array_append_vals(array, array_end, add);
-               added += add;
+       while (array->len < final_size) {
+               g_array_append_vals(array, item, 1);
        }
 }
 
@@ -1870,9 +1873,8 @@ vte_sequence_handler_al(VteTerminal *terminal,
                /* Get the data for the new row. */
                rowdata = _vte_ring_index(screen->row_data, GArray*, start);
                /* Add enough cells to it so that it has the default colors. */
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, screen->defaults);
-               }
+               vte_g_array_fill(rowdata, &screen->defaults,
+                                terminal->column_count);
        }
 
        /* Update the display. */
@@ -2046,9 +2048,7 @@ vte_sequence_handler_ce(VteTerminal *terminal,
                g_array_remove_index(rowdata, rowdata->len - 1);
        }
        /* Add enough cells to the end of the line to fill out the row. */
-       while (rowdata->len < terminal->column_count) {
-               g_array_append_val(rowdata, screen->defaults);
-       }
+       vte_g_array_fill(rowdata, &screen->defaults, terminal->column_count);
        /* Repaint this row. */
        vte_invalidate_cells(terminal,
                             0, terminal->column_count,
@@ -2144,9 +2144,8 @@ vte_sequence_handler_clear_current_line(VteTerminal *terminal,
                }
                /* Add enough cells to the end of the line to fill out the
                 * row. */
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, screen->defaults);
-               }
+               vte_g_array_fill(rowdata, &screen->defaults,
+                                terminal->column_count);
                /* Repaint this row. */
                vte_invalidate_cells(terminal,
                                     0, terminal->column_count,
@@ -2328,9 +2327,8 @@ vte_sequence_handler_dc(VteTerminal *terminal,
                        g_array_remove_index(rowdata, col);
                }
                /* Add new cells until we have enough to fill the row. */
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, screen->defaults);
-               }
+               vte_g_array_fill(rowdata, &screen->defaults,
+                                terminal->column_count);
                /* Repaint this row. */
                vte_invalidate_cells(terminal,
                                     0, terminal->column_count,
@@ -2407,7 +2405,6 @@ vte_terminal_ensure_cursor(VteTerminal *terminal, gboolean current)
        VteScreen *screen;
        struct vte_charcell cell;
        gboolean readjust = FALSE;
-       long add, i;
 
        /* Must make sure we're in a sane area. */
        screen = terminal->pvt->screen;
@@ -2437,25 +2434,7 @@ vte_terminal_ensure_cursor(VteTerminal *terminal, gboolean current)
                }
                /* Add enough cells at the end to make sure we have
                 * enough for all visible columns. */
-               add = screen->cursor_current.col - array->len;
-               if (add > 0) {
-                       vte_g_array_append(array,
-                                          &g_array_index(array,
-                                                         struct vte_charcell,
-                                                         array->len),
-                                          &cell,
-                                          add);
-#ifdef VTE_DEBUG
-                       for (i = 0; i < add; i++) {
-                               struct vte_charcell *newcell;
-                               newcell = &g_array_index(array,
-                                                        struct vte_charcell,
-                                                        array->len - 1 - i);
-                               g_assert(memcmp(newcell, &cell,
-                                               sizeof(cell)) == 0);
-                       }
-#endif
-               }
+               vte_g_array_fill(array, &cell, screen->cursor_current.col);
        }
 }
 
@@ -2699,7 +2678,7 @@ vte_sequence_handler_ke(VteTerminal *terminal,
                        GQuark match_quark,
                        GValueArray *params)
 {
-       terminal->pvt->keypad = VTE_KEYPAD_NORMAL;
+       terminal->pvt->keypad_mode = VTE_KEYMODE_NORMAL;
 }
 
 /* Keypad mode start. */
@@ -2709,7 +2688,7 @@ vte_sequence_handler_ks(VteTerminal *terminal,
                        GQuark match_quark,
                        GValueArray *params)
 {
-       terminal->pvt->keypad = VTE_KEYPAD_APPLICATION;
+       terminal->pvt->keypad_mode = VTE_KEYMODE_APPLICATION;
 }
 
 /* Cursor left. */
@@ -3042,6 +3021,7 @@ vte_sequence_handler_sf(VteTerminal *terminal,
        } else {
                /* Otherwise, just move the cursor down. */
                screen->cursor_current.row++;
+               vte_terminal_ensure_cursor(terminal, TRUE);
        }
 }
 
@@ -3573,9 +3553,8 @@ vte_sequence_handler_clear_above_current(VteTerminal *terminal,
                                g_array_remove_index(rowdata, rowdata->len - 1);
                        }
                        /* Add new cells until we fill the row. */
-                       while (rowdata->len < terminal->column_count) {
-                               g_array_append_val(rowdata, screen->defaults);
-                       }
+                       vte_g_array_fill(rowdata, &screen->defaults,
+                                        terminal->column_count);
                        /* Repaint the row. */
                        vte_invalidate_cells(terminal,
                                             0, terminal->column_count,
@@ -3605,9 +3584,8 @@ vte_sequence_handler_clear_screen(VteTerminal *terminal,
                rowdata = vte_new_row_data_sized(terminal->column_count);
                _vte_ring_append(screen->row_data, rowdata);
                /* Add new cells until we have enough to fill out the row. */
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, screen->defaults);
-               }
+               vte_g_array_fill(rowdata, &screen->defaults,
+                                terminal->column_count);
        }
        /* Move the cursor and insertion delta to the first line in the
         * newly-cleared area and scroll if need be. */
@@ -3870,11 +3848,13 @@ vte_sequence_handler_decset_internal(VteTerminal *terminal,
                gpointer tvalue;
                VteTerminalSequenceHandler reset, set;
        } settings[] = {
-               /* Application/normal keypad. */
-               {1, NULL, &terminal->pvt->keypad, NULL,
-                GINT_TO_POINTER(VTE_KEYPAD_NORMAL),
-                GINT_TO_POINTER(VTE_KEYPAD_APPLICATION),
+               /* Application/normal cursor keys. */
+               {1, NULL, &terminal->pvt->cursor_mode, NULL,
+                GINT_TO_POINTER(VTE_KEYMODE_NORMAL),
+                GINT_TO_POINTER(VTE_KEYMODE_APPLICATION),
                 NULL, NULL,},
+               /* 2: disallowed, we don't do VT52. */
+               /* 3: disallowed, window size is set by user. */
                /* Smooth scroll. */
                {4, &terminal->pvt->smooth_scroll, NULL, NULL,
                 GINT_TO_POINTER(FALSE),
@@ -3897,6 +3877,7 @@ vte_sequence_handler_decset_internal(VteTerminal *terminal,
                 GINT_TO_POINTER(FALSE),
                 GINT_TO_POINTER(TRUE),
                 NULL, NULL,},
+               /* 8: disallowed, keyboard repeat is set by user. */
                /* Send-coords-on-click. */
                {9, &terminal->pvt->mouse_send_xy_on_click, NULL, NULL,
                 GINT_TO_POINTER(FALSE),
@@ -3907,31 +3888,48 @@ vte_sequence_handler_decset_internal(VteTerminal *terminal,
                 GINT_TO_POINTER(FALSE),
                 GINT_TO_POINTER(TRUE),
                 NULL, NULL,},
+               /* 30: disallowed, scrollbar visibility is set by user. */
+               /* 40: disallowed, the user sizes dynamically. */
                /* Alternate screen. */
                {47, NULL, NULL, (gpointer*) &terminal->pvt->screen,
                 &terminal->pvt->normal_screen,
                 &terminal->pvt->alternate_screen,
                 NULL, NULL,},
+               /* Keypad mode. */
+               {66, &terminal->pvt->keypad_mode, NULL, NULL,
+                GINT_TO_POINTER(VTE_KEYMODE_NORMAL),
+                GINT_TO_POINTER(VTE_KEYMODE_APPLICATION),
+                NULL, NULL,},
+               /* 67: disallowed, backspace key policy is set by user. */
                /* Send-coords-on-button. */
                {1000, &terminal->pvt->mouse_send_xy_on_button, NULL, NULL,
                 GINT_TO_POINTER(FALSE),
                 GINT_TO_POINTER(TRUE),
                 NULL, NULL,},
-               /* Hilite tracking*/
+               /* Hilite tracking*/
                {1001, &terminal->pvt->mouse_hilite_tracking, NULL, NULL,
                 GINT_TO_POINTER(FALSE),
                 GINT_TO_POINTER(TRUE),
                 NULL, NULL,},
-               /* Cell motion tracking*/
+               /* Cell motion tracking*/
                {1002, &terminal->pvt->mouse_cell_motion_tracking, NULL, NULL,
                 GINT_TO_POINTER(FALSE),
                 GINT_TO_POINTER(TRUE),
                 NULL, NULL,},
-               /* All motion tracking*/
+               /* All motion tracking*/
                {1003, &terminal->pvt->mouse_all_motion_tracking, NULL, NULL,
                 GINT_TO_POINTER(FALSE),
                 GINT_TO_POINTER(TRUE),
                 NULL, NULL,},
+               /* 1010: disallowed, scroll-on-output is set by user. */
+               /* 1011: disallowed, scroll-on-keypress is set by user. */
+               /* 1035: disallowed, don't know what to do with it. */
+               /* Meta-sends-escape. */
+               {1036, &terminal->pvt->meta_sends_escape, NULL, NULL,
+                GINT_TO_POINTER(FALSE),
+                GINT_TO_POINTER(TRUE),
+                NULL, NULL,},
+               /* 1037: disallowed, delete key policy is set by user. */
                /* Use alternate screen buffer. */
                {1047, NULL, NULL, (gpointer*) &terminal->pvt->screen,
                 &terminal->pvt->normal_screen,
@@ -3949,10 +3947,25 @@ vte_sequence_handler_decset_internal(VteTerminal *terminal,
                 &terminal->pvt->alternate_screen,
                 vte_sequence_handler_rc,
                 vte_sequence_handler_sc,},
-               /* Sun/VT220 keyboard mode. */
-               {1051, NULL, NULL, (gpointer*) &terminal->pvt->fkey,
-                GINT_TO_POINTER(VTE_FKEY_VT220),
-                GINT_TO_POINTER(VTE_FKEY_SUNPC),
+               /* Sun function key mode. */
+               {1051, NULL, NULL, (gpointer*) &terminal->pvt->sun_fkey_mode,
+                GINT_TO_POINTER(FALSE),
+                GINT_TO_POINTER(TRUE),
+                NULL, NULL},
+               /* HP function key mode. */
+               {1052, NULL, NULL, (gpointer*) &terminal->pvt->hp_fkey_mode,
+                GINT_TO_POINTER(FALSE),
+                GINT_TO_POINTER(TRUE),
+                NULL, NULL},
+               /* Legacy function key mode. */
+               {1060, NULL, NULL, (gpointer*) &terminal->pvt->legacy_fkey_mode,
+                GINT_TO_POINTER(FALSE),
+                GINT_TO_POINTER(TRUE),
+                NULL, NULL},
+               /* VT220 function key mode. */
+               {1061, NULL, NULL, (gpointer*) &terminal->pvt->vt220_fkey_mode,
+                GINT_TO_POINTER(FALSE),
+                GINT_TO_POINTER(TRUE),
                 NULL, NULL},
        };
 
@@ -4029,6 +4042,7 @@ vte_sequence_handler_decset_internal(VteTerminal *terminal,
 
        /* Do whatever's necessary when the setting changes. */
        switch (setting) {
+       case 3:
        case 5:
                /* Repaint everything in reverse mode. */
                vte_invalidate_all(terminal);
@@ -4085,7 +4099,7 @@ vte_sequence_handler_application_keypad(VteTerminal *terminal,
                                        GQuark match_quark,
                                        GValueArray *params)
 {
-       terminal->pvt->keypad = VTE_KEYPAD_APPLICATION;
+       terminal->pvt->keypad_mode = VTE_KEYMODE_APPLICATION;
 }
 
 static void
@@ -4094,7 +4108,7 @@ vte_sequence_handler_normal_keypad(VteTerminal *terminal,
                                   GQuark match_quark,
                                   GValueArray *params)
 {
-       terminal->pvt->keypad = VTE_KEYPAD_NORMAL;
+       terminal->pvt->keypad_mode = VTE_KEYMODE_NORMAL;
 }
 
 /* Move the cursor. */
@@ -4387,9 +4401,8 @@ vte_sequence_handler_insert_lines(VteTerminal *terminal,
                /* Get the data for the new row. */
                rowdata = _vte_ring_index(screen->row_data, GArray*, row);
                /* Add enough cells to it so that it has the default colors. */
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, screen->defaults);
-               }
+               vte_g_array_fill(rowdata, &screen->defaults,
+                                terminal->column_count);
        }
        /* Update the display. */
        vte_terminal_scroll_region(terminal, row, end - row + 1, param);
@@ -4432,9 +4445,8 @@ vte_sequence_handler_delete_lines(VteTerminal *terminal,
                /* Get the data for the new row. */
                rowdata = _vte_ring_index(screen->row_data, GArray*, end);
                /* Add enough cells to it so that it has the default colors. */
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, screen->defaults);
-               }
+               vte_g_array_fill(rowdata, &screen->defaults,
+                                terminal->column_count);
        }
        /* Update the display. */
        vte_terminal_scroll_region(terminal, row, end - row + 1, -param);
@@ -4640,9 +4652,7 @@ vte_sequence_handler_screen_alignment_test(VteTerminal *terminal,
                cell = screen->basic_defaults;
                cell.c = 'E';
                cell.columns = 1;
-               while (rowdata->len < terminal->column_count) {
-                       g_array_append_val(rowdata, cell);
-               }
+               vte_g_array_fill(rowdata, &cell, terminal->column_count);
        }
        vte_invalidate_all(terminal);
 }
@@ -5760,9 +5770,7 @@ vte_terminal_insert_char(VteTerminal *terminal, gunichar c,
                if (array->len <= col) {
                        /* Add enough cells to fill out the row to at least out
                         * to the insertion point. */
-                       while (array->len < col) {
-                               array = g_array_append_val(array, cell);
-                       }
+                       vte_g_array_fill(array, &cell, col);
                        /* Add one more cell to the end of the line to get
                         * it into the column, and use it. */
                        array = g_array_append_val(array, cell);
@@ -6598,7 +6606,9 @@ vte_terminal_feed(VteTerminal *terminal, const char *data, glong length)
            (_vte_buffer_length(terminal->pvt->incoming) > 0)) {
 #ifdef VTE_DEBUG
                if (_vte_debug_on(VTE_DEBUG_IO)) {
-                       fprintf(stderr, "Queuing handler to process bytes.\n");
+                       fprintf(stderr,
+                               "Queuing handler to process %ld bytes.\n",
+                               (long) length);
                }
 #endif
                terminal->pvt->processing = TRUE;
@@ -6693,21 +6703,29 @@ vte_terminal_send(VteTerminal *terminal, const char *encoding,
                g_warning(_("Error (%s) converting data for child, dropping."),
                          strerror(errno));
        } else {
-               /* Add the data to the outgoing buffer. */
-               _vte_buffer_append(terminal->pvt->outgoing,
-                                  obufptr, obuf - obufptr);
-               /* If we need to start waiting for the child pty to become
-                * available for writing, set that up here. */
-               if (terminal->pvt->pty_output == NULL) {
-                       terminal->pvt->pty_output =
-                               g_io_channel_unix_new(terminal->pvt->pty_master);
-                       terminal->pvt->pty_output_source =
-                               g_io_add_watch_full(terminal->pvt->pty_output,
-                                                   VTE_CHILD_OUTPUT_PRIORITY,
-                                                   G_IO_OUT,
-                                                   vte_terminal_io_write,
-                                                   terminal,
-                                                   NULL);
+               /* Tell observers that we're sending this to the child. */
+               if (obuf - obufptr > 0) {
+                       vte_terminal_emit_commit(terminal,
+                                                obufptr, obuf - obufptr);
+               }
+               /* If there's a place for it to go, add the data to the
+                * outgoing buffer. */
+               if (terminal->pvt->pty_master != -1) {
+                       _vte_buffer_append(terminal->pvt->outgoing,
+                                          obufptr, obuf - obufptr);
+                       /* If we need to start waiting for the child pty to
+                        * become available for writing, set that up here. */
+                       if (terminal->pvt->pty_output == NULL) {
+                               terminal->pvt->pty_output =
+                                       g_io_channel_unix_new(terminal->pvt->pty_master);
+                               terminal->pvt->pty_output_source =
+                                       g_io_add_watch_full(terminal->pvt->pty_output,
+                                                           VTE_CHILD_OUTPUT_PRIORITY,
+                                                           G_IO_OUT,
+                                                           vte_terminal_io_write,
+                                                           terminal,
+                                                           NULL);
+                       }
                }
        }
        return;
@@ -6897,53 +6915,6 @@ vte_terminal_style_changed(GtkWidget *widget, GtkStyle *style, gpointer data)
        }
 }
 
-static const struct {
-       gulong keyval;
-       char *special;
-       char *vt_ctrl_special;
-} vte_keysym_map[] = {
-       {GDK_F1,     "k1", "F3"},
-       {GDK_KP_F1,  "k1", "F3"},
-       {GDK_F2,     "k2", "F4"},
-       {GDK_KP_F2,  "k2", "F4"},
-       {GDK_F3,     "k3", "F5"},
-       {GDK_KP_F3,  "k3", "F5"},
-       {GDK_F4,     "k4", "F6"},
-       {GDK_KP_F4,  "k4", "F6"},
-       {GDK_F5,     "k5", "F7"},
-       {GDK_F6,     "k6", "F8"},
-       {GDK_F7,     "k7", "F9"},
-       {GDK_F8,     "k8", "FA"},
-       {GDK_F9,     "k9", "FB"},
-       {GDK_F10,    "k;", "FC"},
-       {GDK_F11,    "F1", NULL},
-       {GDK_F12,    "F2", NULL},
-
-       {GDK_F13,    "F3", NULL},
-       {GDK_F14,    "F4", NULL},
-       {GDK_F15,    "F5", NULL},
-       {GDK_F16,    "F6", NULL},
-       {GDK_F17,    "F7", NULL},
-       {GDK_F18,    "F8", NULL},
-       {GDK_F19,    "F9", NULL},
-       {GDK_F20,    "FA", NULL},
-       {GDK_F21,    "FB", NULL},
-       {GDK_F22,    "FC", NULL},
-       {GDK_F23,    "FD", NULL},
-       {GDK_F24,    "FE", NULL},
-       {GDK_F25,    "FF", NULL},
-       {GDK_F26,    "FG", NULL},
-       {GDK_F27,    "FH", NULL},
-       {GDK_F28,    "FI", NULL},
-       {GDK_F29,    "FJ", NULL},
-       {GDK_F30,    "FK", NULL},
-       {GDK_F31,    "FL", NULL},
-       {GDK_F32,    "FM", NULL},
-       {GDK_F33,    "FN", NULL},
-       {GDK_F34,    "FO", NULL},
-       {GDK_F35,    "FP", NULL},
-};
-
 /* Read and handle a keypress event. */
 static gint
 vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
@@ -6954,14 +6925,17 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
        PangoFontDescription *fontdesc;
        struct _vte_termcap *termcap;
        const char *tterm;
-       char *normal = NULL;
+       char *normal = NULL, *output;
        gssize normal_length = 0;
        int i;
-       char *special = NULL, *specialmods = NULL;
+       const char *special = NULL;
        struct termios tio;
        struct timeval tv;
        struct timezone tz;
-       gboolean scrolled = FALSE, steal = FALSE, modifier = FALSE;
+       gboolean scrolled = FALSE, steal = FALSE, modifier = FALSE, handled;
+       VteKeymode keypad_mode = VTE_KEYMODE_NORMAL,
+                  cursor_mode = VTE_KEYMODE_NORMAL;
+       guint keyval = 0;
 
        g_return_val_if_fail(widget != NULL, FALSE);
        g_return_val_if_fail(VTE_IS_TERMINAL(widget), FALSE);
@@ -6970,10 +6944,15 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
        /* If it's a keypress, record that we got the event, in case the
         * input method takes the event from us. */
        if (event->type == GDK_KEY_PRESS) {
+               /* Store a copy of the key. */
+               keyval = event->keyval;
+
+               /* Log the time of the last keypress. */
                if (gettimeofday(&tv, &tz) == 0) {
                        terminal->pvt->last_keypress_time =
                                (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
                }
+
                /* Read the modifiers. */
                if (gdk_event_get_state((GdkEvent*)event,
                                        &modifiers) == FALSE) {
@@ -6981,53 +6960,31 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                }
 #ifdef VTE_DEBUG
                if (_vte_debug_on(VTE_DEBUG_EVENTS)) {
-                       fprintf(stderr, "Keypress, modifiers=%d, keyval=%d, "
-                               "string=`%s'.\n", modifiers, event->keyval,
-                               event->string);
+                       fprintf(stderr, "Keypress, modifiers=0x%x, "
+                               "keyval=0x%x, string=`%s'.\n",
+                               modifiers, keyval, event->string);
                }
 #endif
-               /* Determine if this is just a modifier key. */
-               switch (event->keyval) {
-               case GDK_Alt_L:
-               case GDK_Alt_R:
-               case GDK_Caps_Lock:
-               case GDK_Control_L:
-               case GDK_Control_R:
-               case GDK_Eisu_Shift:
-               case GDK_Hyper_L:
-               case GDK_Hyper_R:
-               case GDK_ISO_First_Group_Lock:
-               case GDK_ISO_Group_Lock:
-               case GDK_ISO_Group_Shift:
-               case GDK_ISO_Last_Group_Lock:
-               case GDK_ISO_Level3_Lock:
-               case GDK_ISO_Level3_Shift:
-               case GDK_ISO_Lock:
-               case GDK_ISO_Next_Group_Lock:
-               case GDK_ISO_Prev_Group_Lock:
-               case GDK_Kana_Lock:
-               case GDK_Kana_Shift:
-               case GDK_Meta_L:
-               case GDK_Meta_R:
-               case GDK_Num_Lock:
-               case GDK_Scroll_Lock:
-               case GDK_Shift_L:
-               case GDK_Shift_Lock:
-               case GDK_Shift_R:
-               case GDK_Super_L:
-               case GDK_Super_R:
-                       modifier = TRUE;
-                       break;
-               default:
-                       modifier = FALSE;
-                       break;
+
+               /* Determine what the keypad and modes are. */
+               if ((modifiers & VTE_NUMLOCK_MASK) == VTE_NUMLOCK_MASK) {
+                       keypad_mode = VTE_KEYMODE_NORMAL;
+               } else {
+                       keypad_mode = terminal->pvt->keypad_mode;
                }
+               cursor_mode = terminal->pvt->cursor_mode;
+
+               /* Determine if this is just a modifier key. */
+               modifier = _vte_keymap_key_is_modifier(keyval);
+
                /* Unless it's a modifier key, hide the pointer. */
                if (!modifier) {
                        vte_terminal_set_pointer_visible(terminal, FALSE);
                }
-               /* Determine if this is a key we want to steal. */
-               switch (event->keyval) {
+
+               /* Determine if this is a key we want to steal from the
+                * input method. */
+               switch (keyval) {
                case GDK_KP_Add:
                case GDK_KP_Subtract:
                        if (modifiers & GDK_SHIFT_MASK) {
@@ -7054,8 +7011,9 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
 
        /* Now figure out what to send to the child. */
        if (event->type == GDK_KEY_PRESS) {
+               handled = FALSE;
                /* Map the key to a sequence name if we can. */
-               switch (event->keyval) {
+               switch (keyval) {
                case GDK_BackSpace:
                        switch (terminal->pvt->backspace_binding) {
                        case VTE_ERASE_ASCII_BACKSPACE:
@@ -7082,6 +7040,7 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                                }
                                break;
                        }
+                       handled = TRUE;
                        break;
                case GDK_KP_Delete:
                case GDK_Delete:
@@ -7100,6 +7059,7 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                                special = "kD";
                                break;
                        }
+                       handled = TRUE;
                        break;
                case GDK_KP_Insert:
                case GDK_Insert:
@@ -7109,105 +7069,15 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                        } else {
                                special = "kI";
                        }
+                       handled = TRUE;
                        break;
-               case GDK_KP_Home:
-               case GDK_Home:
-                       special = "kh";
-                       break;
-               case GDK_KP_End:
-               case GDK_End:
-                       special = "@7";
-                       break;
-               case GDK_F1:
-               case GDK_F2:
-               case GDK_F3:
-               case GDK_F4:
-               case GDK_F5:
-               case GDK_F6:
-               case GDK_F7:
-               case GDK_F8:
-               case GDK_F9:
-               case GDK_F10:
-               case GDK_F11:
-               case GDK_F12:
-               case GDK_F13:
-               case GDK_F14:
-               case GDK_F15:
-               case GDK_F16:
-               case GDK_F17:
-               case GDK_F18:
-               case GDK_F19:
-               case GDK_F20:
-               case GDK_F21:
-               case GDK_F22:
-               case GDK_F23:
-               case GDK_F24:
-               case GDK_F25:
-               case GDK_F26:
-               case GDK_F27:
-               case GDK_F28:
-               case GDK_F29:
-               case GDK_F30:
-               case GDK_F31:
-               case GDK_F32:
-               case GDK_F33:
-               case GDK_F34:
-               case GDK_F35:
-                       for (i = 0;
-                            i < G_N_ELEMENTS(vte_keysym_map);
-                            i++) {
-                               if (vte_keysym_map[i].keyval == event->keyval) {
-                                       if (terminal->pvt->fkey == VTE_FKEY_VT220) {
-                                               if ((modifiers & GDK_CONTROL_MASK) && vte_keysym_map[i].vt_ctrl_special) {
-                                                       special = vte_keysym_map[i].vt_ctrl_special;
-                                               } else {
-                                                       special = vte_keysym_map[i].special;
-                                               }
-                                       }
-                                       if (terminal->pvt->fkey == VTE_FKEY_SUNPC) {
-                                               special = vte_keysym_map[i].special;
-                                               i = 0;
-                                               if (modifiers & GDK_CONTROL_MASK) {
-                                                       i += 4;
-                                               }
-                                               if (modifiers & GDK_MOD1_MASK) {
-                                                       i += 2;
-                                               }
-                                               if (modifiers & GDK_SHIFT_MASK) {
-                                                       i += 1;
-                                               }
-                                               if (i > 0) {
-                                                       specialmods = g_strdup_printf("%d", i + 1);
-                                               }
-                                       }
-                                       break;
-                               }
-                       }
-                       break;
-               /* Cursor keys. */
-               case GDK_KP_Up:
-               case GDK_Up:
-                       special = "ku";
-                       break;
-               case GDK_KP_Down:
-               case GDK_Down:
-                       special = "kd";
-                       break;
-               case GDK_KP_Left:
-               case GDK_Left:
-                       special = "kl";
-                       break;
-               case GDK_KP_Right:
-               case GDK_Right:
-                       special = "kr";
-                       break;
+               /* Keypad/motion keys. */
                case GDK_KP_Page_Up:
                case GDK_Page_Up:
                        if (modifiers & GDK_SHIFT_MASK) {
                                vte_terminal_scroll_pages(terminal, -1);
                                scrolled = TRUE;
-                       } else {
-                               special = "kP";
+                               handled = TRUE;
                        }
                        break;
                case GDK_KP_Page_Down:
@@ -7215,31 +7085,7 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                        if (modifiers & GDK_SHIFT_MASK) {
                                vte_terminal_scroll_pages(terminal, 1);
                                scrolled = TRUE;
-                       } else {
-                               special = "kN";
-                       }
-                       break;
-               case GDK_KP_Tab:
-               case GDK_Tab:
-                       if (modifiers & GDK_SHIFT_MASK) {
-                               special = "kB";
-                       } else {
-                               normal = g_strdup("\t");
-                               normal_length = 1;
-                       }
-                       break;
-               case GDK_ISO_Left_Tab:
-                       special = "kB";
-                       break;
-               case GDK_KP_Space:
-               case GDK_space:
-                       if (modifiers & GDK_CONTROL_MASK) {
-                               /* Ctrl-Space sends NUL?!?  Madness! */
-                               normal = g_strdup("");
-                               normal_length = 1;
-                       } else {
-                               normal = g_strdup(" ");
-                               normal_length = 1;
+                               handled = TRUE;
                        }
                        break;
                /* Let Shift +/- tweak the font, like XTerm does. */
@@ -7251,10 +7097,10 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                                if (rofontdesc != NULL) {
                                        fontdesc = pango_font_description_copy(rofontdesc);
                                        i = pango_font_description_get_size(fontdesc);
-                                       if (event->keyval == GDK_KP_Add) {
+                                       if (keyval == GDK_KP_Add) {
                                                i += PANGO_SCALE;
                                        }
-                                       if (event->keyval == GDK_KP_Subtract) {
+                                       if (keyval == GDK_KP_Subtract) {
                                                i = MAX(PANGO_SCALE,
                                                        i - PANGO_SCALE);
                                        }
@@ -7267,6 +7113,7 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                                        pango_font_description_set_size(fontdesc, i);
                                        vte_terminal_set_font(terminal, fontdesc);
                                        pango_font_description_free(fontdesc);
+                                       handled = TRUE;
                                }
 #ifdef VTE_DEBUG
                                if (_vte_debug_on(VTE_DEBUG_MISC)) {
@@ -7275,33 +7122,48 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                                        }
                                }
 #endif
-                               break;
                        }
                        break;
-               /* The default is to just send the string. */
                default:
-                       if (event->string != NULL) {
-                               normal = g_strdup(event->string);
-                               normal_length = strlen(normal);
-                               if (modifiers & GDK_CONTROL_MASK) {
-                                       /* Replace characters which have
-                                        * "control" counterparts with
-                                        * those counterparts. */
-                                       for (i = 0; i < normal_length; i++) {
-                                               if ((normal[i] > 64) &&
-                                                   (normal[i] < 97)) {
-                                                       normal[i] ^= 0x40;
-                                               }
+                       break;
+               }
+               /* If the above switch statement didn't do the job, try mapping
+                * it to a literal or capability name. */
+               if (handled == FALSE) {
+                       _vte_keymap_map(keyval, modifiers,
+                                       terminal->pvt->sun_fkey_mode,
+                                       terminal->pvt->hp_fkey_mode,
+                                       terminal->pvt->legacy_fkey_mode,
+                                       terminal->pvt->vt220_fkey_mode,
+                                       terminal->pvt->cursor_mode == VTE_KEYMODE_APPLICATION,
+                                       terminal->pvt->keypad_mode == VTE_KEYMODE_APPLICATION,
+                                       &normal,
+                                       &normal_length,
+                                       &special);
+               }
+               /* If we didn't manage to do anything, try to salvage a
+                * printable string. */
+               if (!handled &&
+                   (normal == NULL) && (special == NULL) &&
+                   (event->string != NULL)) {
+                       normal = g_strdup(event->string);
+                       normal_length = strlen(normal);
+                       if (modifiers & GDK_CONTROL_MASK) {
+                               /* Replace characters which have "control"
+                                * counterparts with those counterparts. */
+                               for (i = 0; i < normal_length; i++) {
+                                       if ((normal[i] >= 0x40) &&
+                                           (normal[i] <= 0x60)) {
+                                               normal[i] ^= 0x40;
                                        }
                                }
                        }
-                       break;
                }
                /* If we got normal characters, send them to the child. */
                if (normal != NULL) {
-                       if (terminal->pvt->alt_sends_escape &&
+                       if (terminal->pvt->meta_sends_escape &&
                            (normal_length > 0) &&
-                           (modifiers & GDK_MOD1_MASK)) {
+                           (modifiers & VTE_META_MASK)) {
                                vte_terminal_feed_child(terminal, "\e", 1);
                        }
                        if (normal_length > 0) {
@@ -7318,22 +7180,9 @@ vte_terminal_key_press(GtkWidget *widget, GdkEventKey *event)
                                                                 tterm,
                                                                 special,
                                                                 &normal_length);
-                       special = g_strdup_printf(normal, 1);
-                       if (specialmods) {
-                               i = strlen(special);
-                               if ((i > 0) && (special[i - 1] == '~')) {
-                                       /* Insert the modifier before the
-                                        * last character, which is '~'. */
-                                       special = g_realloc(special,
-                                                           i + strlen(specialmods) + 2);
-                                       special[i - 1] = ';';
-                                       strcpy(special + i, specialmods);
-                                       strcat(special + i + strlen(specialmods), "~");
-                               }
-                               g_free(specialmods);
-                       }
-                       vte_terminal_feed_child(terminal, special, -1);
-                       g_free(special);
+                       output = g_strdup_printf(normal, 1);
+                       vte_terminal_feed_child(terminal, output, -1);
+                       g_free(output);
                        g_free(normal);
                }
                /* Keep the cursor on-screen. */
@@ -8272,9 +8121,8 @@ vte_terminal_get_text_range(VteTerminal *terminal,
                        /* If we added a character to the string, record its
                         * attributes, one per byte. */
                        if (attributes) {
-                               while (attributes->len < string->len) {
-                                       g_array_append_val(attributes, attr);
-                               }
+                               vte_g_array_fill(attributes,
+                                                &attr, string->len);
                        }
                        col++;
                        if ((col >= terminal->column_count) ||
@@ -8282,9 +8130,14 @@ vte_terminal_get_text_range(VteTerminal *terminal,
                                break;
                        }
                } while (pcell != NULL);
-               /* Extra spaces at the end of a line become newlines. */
+               /* Extra spaces at the end of a line become newlines unless
+                * this is the last row of the selection. */
                if (spaces > 0) {
-                       string = g_string_append_c(string, '\n');
+                       if (row != end_row) {
+                               string = g_string_append_c(string, '\n');
+                       } else {
+                               string = g_string_append_c(string, ' ');
+                       }
                        spaces = 0;
                        attr.column = col;
                }
@@ -8292,7 +8145,8 @@ vte_terminal_get_text_range(VteTerminal *terminal,
                 * with missing attributes. */
                if (attributes) {
                        while (attributes->len < string->len) {
-                               g_array_append_val(attributes, attr);
+                               vte_g_array_fill(attributes,
+                                                &attr, string->len);
                        }
                }
        }
@@ -10059,8 +9913,12 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
        pvt->flags.am = FALSE;
        pvt->flags.bw = FALSE;
        pvt->flags.ul = FALSE;
-       pvt->keypad = VTE_KEYPAD_NORMAL;
-       pvt->fkey = VTE_FKEY_VT220;
+       pvt->keypad_mode = VTE_KEYMODE_NORMAL;
+       pvt->cursor_mode = VTE_KEYMODE_NORMAL;
+       pvt->sun_fkey_mode = FALSE;
+       pvt->hp_fkey_mode = FALSE;
+       pvt->legacy_fkey_mode = FALSE;
+       pvt->vt220_fkey_mode = FALSE;
        pvt->dec_saved = g_hash_table_new(g_direct_hash, g_direct_equal);
        pvt->default_column_count = 80;
        pvt->default_row_count = 24;
@@ -10167,7 +10025,7 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
        /* Miscellaneous options. */
        vte_terminal_set_backspace_binding(terminal, VTE_ERASE_AUTO);
        vte_terminal_set_delete_binding(terminal, VTE_ERASE_AUTO);
-       pvt->alt_sends_escape = TRUE;
+       pvt->meta_sends_escape = TRUE;
        pvt->audible_bell = TRUE;
        pvt->visible_bell = FALSE;
        pvt->xterm_font_tweak = FALSE;
@@ -12688,6 +12546,15 @@ vte_terminal_class_init(VteTerminalClass *klass, gconstpointer data)
                             NULL,
                             _vte_marshal_VOID__VOID,
                             G_TYPE_NONE, 0);
+       klass->commit_signal =
+               g_signal_new("commit",
+                            G_OBJECT_CLASS_TYPE(klass),
+                            G_SIGNAL_RUN_LAST,
+                            0,
+                            NULL,
+                            NULL,
+                            _vte_marshal_VOID__STRING_UINT,
+                            G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT);
        klass->emulation_changed_signal =
                g_signal_new("emulation-changed",
                             G_OBJECT_CLASS_TYPE(klass),
@@ -13905,8 +13772,15 @@ vte_terminal_reset(VteTerminal *terminal, gboolean full, gboolean clear_history)
                _vte_iso2022_free(terminal->pvt->substitutions);
        }
        terminal->pvt->substitutions = _vte_iso2022_new();
-       /* Reset appkeypad state. */
-       terminal->pvt->keypad = VTE_KEYPAD_NORMAL;
+       /* Reset keypad/cursor/function key modes. */
+       terminal->pvt->keypad_mode = VTE_KEYMODE_NORMAL;
+       terminal->pvt->cursor_mode = VTE_KEYMODE_NORMAL;
+       terminal->pvt->sun_fkey_mode = FALSE;
+       terminal->pvt->hp_fkey_mode = FALSE;
+       terminal->pvt->legacy_fkey_mode = FALSE;
+       terminal->pvt->vt220_fkey_mode = FALSE;
+       /* Enable meta-sends-escape. */
+       terminal->pvt->meta_sends_escape = TRUE;
        /* Disable smooth scroll. */
        terminal->pvt->smooth_scroll = FALSE;
        /* Reset saved settings. */
index 4d930ab..cd30fed 100644 (file)
--- a/src/vte.h
+++ b/src/vte.h
@@ -87,7 +87,7 @@ struct _VteTerminalClass {
        guint move_window_signal;
        guint status_line_changed_signal;
 
-       gpointer reserved1;
+       guint commit_signal;
        gpointer reserved2;
        gpointer reserved3;
        gpointer reserved4;
index de04177..198e249 100644 (file)
@@ -283,7 +283,9 @@ main(int argc, char **argv)
                                  strlen(message));
        }
 #endif
-       vte_terminal_fork_command(VTE_TERMINAL(widget), command, NULL, env_add);
+       vte_terminal_fork_logged_command(VTE_TERMINAL(widget),
+                                        command, NULL, env_add,
+                                        TRUE, TRUE, TRUE);
        if (command == NULL) {
                vte_terminal_feed_child(VTE_TERMINAL(widget), "pwd\n", -1);
        }
index 592b76e..4b06e37 100644 (file)
@@ -1,5 +1,5 @@
 # This is a cut-down version of the termcap file from my box, with @7, k;, kB,
-# F1-FA added.
+# F1-FA added, and ku/kd/kl/kr changed to the normal cursor mode sequences.
 xterm-xfree86|xterm-new|xterm terminal emulator (XFree86):\
        :am:km:mi:ms:xn:\
        :co#80:it#8:li#24:\
@@ -11,8 +11,8 @@ xterm-xfree86|xterm-new|xterm terminal emulator (XFree86):\
        :ei=\E[4l:ho=\E[H:im=\E[4h:is=\E[!p\E[?3;4l\E[4l\E>:\
        :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[15~:k6=\E[17~:\
        :k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:kD=\177:kI=\E[2~:kN=\E[6~:\
-       :kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kh=\E[1~:kl=\EOD:\
-       :kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:\
+       :kP=\E[5~:kb=^H:kd=\E[B:ke=\E[?1l\E>:kh=\E[1~:kl=\E[D:\
+       :kr=\E[C:ks=\E[?1h\E=:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:\
        :me=\E[m\017:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:\
        :sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E[?1047l\E[?1048l:\
        :ti=\E[?1048h\E[?1047h:ue=\E[24m:up=\E[A:us=\E[4m:\