Hello,

        This is a new path series that fix some problems related to the
keyboard, and also add the key definitions that were missed in st.

Best regards.
>From 22e55d15af79e23a6f78c685a2ed73c3f10db1e1 Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Thu, 8 Nov 2012 16:32:28 +0100
Subject: Add SRM sequence

This sequence enable/disable the local echo.
---
 st.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 56 insertions(+), 20 deletions(-)

diff --git a/st.c b/st.c
index 8b18607..8bf9337 100644
--- a/st.c
+++ b/st.c
@@ -110,17 +110,18 @@ enum glyph_state {
 };
 
 enum term_mode {
-	MODE_WRAP	= 1,
+	MODE_WRAP	 = 1,
 	MODE_INSERT      = 2,
 	MODE_APPKEYPAD   = 4,
 	MODE_ALTSCREEN   = 8,
-	MODE_CRLF	= 16,
+	MODE_CRLF	 = 16,
 	MODE_MOUSEBTN    = 32,
 	MODE_MOUSEMOTION = 64,
 	MODE_MOUSE       = 32|64,
 	MODE_REVERSE     = 128,
 	MODE_KBDLOCK     = 256,
-	MODE_HIDE      = 512
+	MODE_HIDE	 = 512,
+	MODE_ECHO	 = 1024
 };
 
 enum escape_state {
@@ -320,6 +321,7 @@ static void tswapscreen(void);
 static void tsetdirt(int, int);
 static void tsetmode(bool, bool, int *, int);
 static void tfulldirt(void);
+static void techo(char *, int);
 
 static void ttynew(void);
 static void ttyread(void);
@@ -1534,7 +1536,8 @@ tsetmode(bool priv, bool set, int *args, int narg) {
 			case 4:  /* IRM -- Insertion-replacement */
 				MODBIT(term.mode, set, MODE_INSERT);
 				break;
-			case 12: /* XXX: SRM -- Send/Receive */
+			case 12: /* SRM -- Send/Receive */
+				MODBIT(term.mode, !set, MODE_ECHO);
 				break;
 			case 20: /* LNM -- Linefeed/new line */
 				MODBIT(term.mode, set, MODE_CRLF);
@@ -1849,6 +1852,28 @@ tputtab(bool forward) {
 }
 
 void
+techo(char *buf, int len) {
+	for(; len > 0; buf++, len--) {
+		char c = *buf;
+
+		if(c == '\033') {		/* escape */
+			tputc("^", 1);
+			tputc("[", 1);
+		} else if (c < '\x20') {	/* control code */
+			if(c != '\n' && c != '\r' && c != '\t') {
+				c |= '\x40';
+				tputc("^", 1);
+			}
+			tputc(&c, 1);
+		} else {
+			break;
+		}
+	}
+	if (len)
+		tputc(buf, len);
+}
+
+void
 tputc(char *c, int len) {
 	uchar ascii = *c;
 	bool control = ascii < '\x20' || ascii == 0177;
@@ -2679,7 +2704,7 @@ void
 kpress(XEvent *ev) {
 	XKeyEvent *e = &ev->xkey;
 	KeySym ksym;
-	char buf[32], *customkey;
+	char xstr[31], buf[32], *customkey, *cp = buf;
 	int len, meta, shift, i;
 	Status status;
 
@@ -2688,7 +2713,7 @@ kpress(XEvent *ev) {
 
 	meta = e->state & Mod1Mask;
 	shift = e->state & ShiftMask;
-	len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status);
+	len = XmbLookupString(xw.xic, e, xstr, sizeof(xstr), &ksym, &status);
 
 	/* 1. shortcuts */
 	for(i = 0; i < LEN(shortcuts); i++) {
@@ -2702,7 +2727,8 @@ kpress(XEvent *ev) {
 
 	/* 2. custom keys from config.h */
 	if((customkey = kmap(ksym, e->state))) {
-		ttywrite(customkey, strlen(customkey));
+		len = strlen(customkey);
+		memcpy(buf, customkey, len);
 	/* 2. hardcoded (overrides X lookup) */
 	} else {
 		switch(ksym) {
@@ -2714,34 +2740,44 @@ kpress(XEvent *ev) {
 			sprintf(buf, "\033%c%c",
 				IS_SET(MODE_APPKEYPAD) ? 'O' : '[',
 				(shift ? "dacb":"DACB")[ksym - XK_Left]);
-			ttywrite(buf, 3);
+			len = 3;
 			break;
 		case XK_Insert:
-			if(shift)
+			if(shift) {
 				selpaste();
+				return;
+			}
+			memcpy(buf, xstr, len);
 			break;
 		case XK_Return:
+			len = 0;
 			if(meta)
-				ttywrite("\033", 1);
+				*cp++ = '\033', len++;
 
-			if(IS_SET(MODE_CRLF)) {
-				ttywrite("\r\n", 2);
-			} else {
-				ttywrite("\r", 1);
-			}
+			*cp++ = '\r', len++;
+
+			if(IS_SET(MODE_CRLF))
+				*cp = '\n', len++;
 			break;
 			/* 3. X lookup  */
 		default:
-			if(len > 0) {
-				if(meta && len == 1)
-					ttywrite("\033", 1);
-				ttywrite(buf, len);
-			}
+			if(len == 0)
+				return;
+
+			if (len == 1 && meta)
+				*cp++ = '\033';
+
+			memcpy(cp, xstr, len);
+			len = cp - buf + len;
 			break;
 		}
 	}
+	ttywrite(buf, len);
+	if(IS_SET(MODE_ECHO))
+		techo(buf, len);
 }
 
+
 void
 cmessage(XEvent *e) {
 	/* See xembed specs
-- 
1.7.10.4

>From f19b777a627598c1e94512b8e9027793e820b75d Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Fri, 9 Nov 2012 11:21:59 +0100
Subject: Fix keypad mode and cursor mode

Keypad mode is used for detecting when keys in the auxiliary keypad are
pressed, while cursor mode is used for detecting when a cursor is pressed,
but they are different modes.

St was mixing both modes and DECPAM and DECPNM modified the cursor mode, and
this was incorrect.
---
 st.c    |    5 +++--
 st.info |    4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/st.c b/st.c
index 8bf9337..683a0e9 100644
--- a/st.c
+++ b/st.c
@@ -121,7 +121,8 @@ enum term_mode {
 	MODE_REVERSE     = 128,
 	MODE_KBDLOCK     = 256,
 	MODE_HIDE	 = 512,
-	MODE_ECHO	 = 1024
+	MODE_ECHO	 = 1024,
+	MODE_APPCURSOR	 = 2048
 };
 
 enum escape_state {
@@ -1471,7 +1472,7 @@ tsetmode(bool priv, bool set, int *args, int narg) {
 			switch(*args) {
 				break;
 			case 1: /* DECCKM -- Cursor key */
-				MODBIT(term.mode, set, MODE_APPKEYPAD);
+				MODBIT(term.mode, set, MODE_APPCURSOR);
 				break;
 			case 5: /* DECSCNM -- Reverse video */
 				mode = term.mode;
diff --git a/st.info b/st.info
index 58e2139..63af234 100644
--- a/st.info
+++ b/st.info
@@ -89,7 +89,7 @@ st| simpleterm,
 	ritm=\E[23m,
 	rmacs=\E(B,
 	rmcup=\E[?1049l,
-#	rmkx=\E>,
+	rmkx=\E[?1l\E>,
 	rmso=\E[23m,
 	rmul=\E[m,
 	rs1=\Ec,
@@ -104,7 +104,7 @@ st| simpleterm,
 	sitm=\E[3m,
 	smacs=\E(0,
 	smcup=\E[?1049h,
-#	smkx=\E=,
+	smkx=\E[?1h\E=,
 	smso=\E[3m,
 	smul=\E[4m,
 	tbc=\E[3g,
-- 
1.7.10.4

>From ade155e92863bc18e4812ceee55bc97a4be85922 Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Mon, 12 Nov 2012 17:55:30 +0100
Subject: Move Shift + Insert to shortcut

Shift + Insert is used like a hot key for paste the selection, so it is more
logical move it to shortcut array instead of having special code for it.
---
 config.def.h |    1 +
 st.c         |   13 +++----------
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/config.def.h b/config.def.h
index ee677a5..3bf35d9 100644
--- a/config.def.h
+++ b/config.def.h
@@ -93,5 +93,6 @@ static Shortcut shortcuts[] = {
 	/* modifier		key		function	argument */
 	{ MODKEY|ShiftMask,	XK_Prior,	xzoom,		{.i = +1} },
 	{ MODKEY|ShiftMask,	XK_Next,	xzoom,		{.i = -1} },
+	{ ShiftMask,		XK_Insert,	selpaste,	{.i =  0} },
 };
 
diff --git a/st.c b/st.c
index 683a0e9..02a3502 100644
--- a/st.c
+++ b/st.c
@@ -261,6 +261,7 @@ typedef struct {
 
 /* function definitions used in config.h */
 static void xzoom(const Arg *);
+static void selpaste(const Arg *);
 
 /* Config.h for applying patches and the configuration. */
 #include "config.h"
@@ -360,7 +361,6 @@ static void selrequest(XEvent *);
 static void selinit(void);
 static inline bool selected(int, int);
 static void selcopy(void);
-static void selpaste(void);
 static void selscroll(int, int);
 
 static int utf8decode(char *, long *);
@@ -750,7 +750,7 @@ selnotify(XEvent *e) {
 }
 
 void
-selpaste(void) {
+selpaste(const Arg *dummy) {
 	XConvertSelection(xw.dpy, XA_PRIMARY, sel.xtarget, XA_PRIMARY,
 			xw.win, CurrentTime);
 }
@@ -821,7 +821,7 @@ brelease(XEvent *e) {
 	}
 
 	if(e->xbutton.button == Button2) {
-		selpaste();
+		selpaste(NULL);
 	} else if(e->xbutton.button == Button1) {
 		sel.mode = 0;
 		getbuttoninfo(e, NULL, &sel.ex, &sel.ey);
@@ -2743,13 +2743,6 @@ kpress(XEvent *ev) {
 				(shift ? "dacb":"DACB")[ksym - XK_Left]);
 			len = 3;
 			break;
-		case XK_Insert:
-			if(shift) {
-				selpaste();
-				return;
-			}
-			memcpy(buf, xstr, len);
-			break;
 		case XK_Return:
 			len = 0;
 			if(meta)
-- 
1.7.10.4

>From 9d8b97c695ae04d264ee651da519bdf19c661ca5 Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Mon, 12 Nov 2012 18:45:45 +0100
Subject: Remove hardcoded keys form kpress

Some keys were in the Key array while others were hardcoded in
kpress().This cause some problems with some keys which can generate more of
one string based in the configuration of the terminal.
---
 config.def.h |   70 ++++++++++++++++++++++++++++++++++++++++-----------------
 st.c         |   71 +++++++++++++++++++++++++---------------------------------
 2 files changed, 79 insertions(+), 62 deletions(-)

diff --git a/config.def.h b/config.def.h
index 3bf35d9..622499e 100644
--- a/config.def.h
+++ b/config.def.h
@@ -56,34 +56,62 @@ static unsigned int defaultucs = 257;
 
 /*
  * Special keys (change & recompile st.info accordingly)
- * Keep in mind that kpress() in st.c hardcodes some keys.
  *
  * Mask value:
  * * Use XK_ANY_MOD to match the key no matter modifiers state
  * * Use XK_NO_MOD to match the key alone (no modifiers)
+ * keypad value:
+ * * 0: no value
+ * * > 0: keypad application mode enabled
+ * * < 0: keypad application mode disabled
+ * cursor value:
+ * * 0: no value
+ * * > 0: cursor application mode enabled
+ * * < 0: cursor application mode disabled
+ * crlf value
+ * * 0: no value
+ * * > 0: crlf mode is enabled
+ * * < 0: crlf mode is disabled
  */
 
-/* key, mask, output */
+/* key, mask, output, keypad, cursor, crlf */
 static Key key[] = {
-	{ XK_BackSpace, XK_NO_MOD, "\177" },
-	{ XK_Insert,    XK_NO_MOD, "\033[2~" },
-	{ XK_Delete,    XK_NO_MOD, "\033[3~" },
-	{ XK_Home,      XK_NO_MOD, "\033[1~" },
-	{ XK_End,       XK_NO_MOD, "\033[4~" },
-	{ XK_Prior,     XK_NO_MOD, "\033[5~" },
-	{ XK_Next,      XK_NO_MOD, "\033[6~" },
-	{ XK_F1,        XK_NO_MOD, "\033OP"   },
-	{ XK_F2,        XK_NO_MOD, "\033OQ"   },
-	{ XK_F3,        XK_NO_MOD, "\033OR"   },
-	{ XK_F4,        XK_NO_MOD, "\033OS"   },
-	{ XK_F5,        XK_NO_MOD, "\033[15~" },
-	{ XK_F6,        XK_NO_MOD, "\033[17~" },
-	{ XK_F7,        XK_NO_MOD, "\033[18~" },
-	{ XK_F8,        XK_NO_MOD, "\033[19~" },
-	{ XK_F9,        XK_NO_MOD, "\033[20~" },
-	{ XK_F10,       XK_NO_MOD, "\033[21~" },
-	{ XK_F11,       XK_NO_MOD, "\033[23~" },
-	{ XK_F12,       XK_NO_MOD, "\033[24~" },
+	/* keysym             mask         string         keypad cursor crlf */
+	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0,    0},
+	{ XK_Up,            XK_NO_MOD,      "\033[A",        0,   -1,    0},
+	{ XK_Up,            XK_NO_MOD,      "\033OA",        0,   +1,    0},
+	{ XK_Up,            ShiftMask,      "\033[a",        0,    0,    0},
+	{ XK_Down,          XK_NO_MOD,      "\033[B",        0,   -1,    0},
+	{ XK_Down,          XK_NO_MOD,      "\033OB",        0,   +1,    0},
+	{ XK_Down,          ShiftMask,      "\033[b",        0,    0,    0},
+	{ XK_Left,     	    XK_NO_MOD,      "\033[D",        0,   -1,    0},
+	{ XK_Left,          XK_NO_MOD,      "\033OD",        0,   +1,    0},
+	{ XK_Left,          ShiftMask,      "\033[d",        0,    0,    0},
+	{ XK_Right,         XK_NO_MOD,      "\033[C",        0,   -1,    0},
+	{ XK_Right,         XK_NO_MOD,      "\033OC",        0,   +1,    0},
+	{ XK_Right,         ShiftMask,      "\033[c",        0,    0,    0},
+	{ XK_Return,        XK_NO_MOD,      "\n",            0,    0,   -1},
+	{ XK_Return,        XK_NO_MOD,      "\r\n",          0,    0,   +1},
+	{ XK_Return,        Mod1Mask,       "\033\n",        0,    0,   -1},
+	{ XK_Return,        Mod1Mask,       "\033\r\n",      0,    0,   +1},
+	{ XK_Insert,        XK_NO_MOD,      "\033[2~",       0,    0,    0},
+	{ XK_Delete,        XK_NO_MOD,      "\033[3~",       0,    0,    0},
+	{ XK_Home,          XK_NO_MOD,      "\033[1~",       0,    0,    0},
+	{ XK_End,           XK_NO_MOD,      "\033[4~",       0,    0,    0},
+	{ XK_Prior,         XK_NO_MOD,      "\033[5~",       0,    0,    0},
+	{ XK_Next,          XK_NO_MOD,      "\033[6~",       0,    0,    0},
+	{ XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0,    0},
+	{ XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0,    0},
+	{ XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0,    0},
+	{ XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0,    0},
+	{ XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0,    0},
+	{ XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0,    0},
+	{ XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0,    0},
+	{ XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0,    0},
+	{ XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0,    0},
+	{ XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0,    0},
+	{ XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0,    0},
+	{ XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0,    0},
 };
 
 /* Internal shortcuts. */
diff --git a/st.c b/st.c
index 02a3502..14408c5 100644
--- a/st.c
+++ b/st.c
@@ -228,6 +228,10 @@ typedef struct {
 	KeySym k;
 	uint mask;
 	char s[ESC_BUF_SIZ];
+	/* three valued logic variables: 0 indifferent, 1 on, -1 off */
+	signed char appkey;		/* application keypad */
+	signed char appcursor;		/* application cursor */
+	signed char crlf;		/* crlf mode          */
 } Key;
 
 /* TODO: use better name for vars... */
@@ -2686,17 +2690,29 @@ focus(XEvent *ev) {
 
 char*
 kmap(KeySym k, uint state) {
-	int i;
 	uint mask;
+	Key *kp;
 
 	state &= ~Mod2Mask;
-	for(i = 0; i < LEN(key); i++) {
-		mask = key[i].mask;
+	for(kp = key; kp < key + LEN(key); kp++) {
+		mask = kp->mask;
 
-		if(key[i].k == k && ((state & mask) == mask
-				|| (mask == XK_NO_MOD && !state))) {
-			return (char*)key[i].s;
-		}
+		if(kp->k != k)
+			continue;
+		if((state & mask) != mask &&
+		   (mask == XK_NO_MOD && state))
+			continue;
+		if((kp->appkey < 0 && IS_SET(MODE_APPKEYPAD)) ||
+		   (kp->appkey > 0 && !IS_SET(MODE_APPKEYPAD)))
+			continue;
+		if((kp->appcursor < 0 && IS_SET(MODE_APPCURSOR)) ||
+		   (kp->appcursor > 0 && !IS_SET(MODE_APPCURSOR)))
+			continue;
+		if((kp->crlf < 0 && IS_SET(MODE_CRLF)) ||
+		   (kp->crlf > 0 && !IS_SET(MODE_CRLF)))
+			continue;
+
+		return kp->s;
 	}
 	return NULL;
 }
@@ -2706,14 +2722,12 @@ kpress(XEvent *ev) {
 	XKeyEvent *e = &ev->xkey;
 	KeySym ksym;
 	char xstr[31], buf[32], *customkey, *cp = buf;
-	int len, meta, shift, i;
+	int len, i;
 	Status status;
 
 	if (IS_SET(MODE_KBDLOCK))
 		return;
 
-	meta = e->state & Mod1Mask;
-	shift = e->state & ShiftMask;
 	len = XmbLookupString(xw.xic, e, xstr, sizeof(xstr), &ksym, &status);
 
 	/* 1. shortcuts */
@@ -2732,39 +2746,14 @@ kpress(XEvent *ev) {
 		memcpy(buf, customkey, len);
 	/* 2. hardcoded (overrides X lookup) */
 	} else {
-		switch(ksym) {
-		case XK_Up:
-		case XK_Down:
-		case XK_Left:
-		case XK_Right:
-			/* XXX: shift up/down doesn't work */
-			sprintf(buf, "\033%c%c",
-				IS_SET(MODE_APPKEYPAD) ? 'O' : '[',
-				(shift ? "dacb":"DACB")[ksym - XK_Left]);
-			len = 3;
-			break;
-		case XK_Return:
-			len = 0;
-			if(meta)
-				*cp++ = '\033', len++;
-
-			*cp++ = '\r', len++;
-
-			if(IS_SET(MODE_CRLF))
-				*cp = '\n', len++;
-			break;
-			/* 3. X lookup  */
-		default:
-			if(len == 0)
-				return;
+		if(len == 0)
+			return;
 
-			if (len == 1 && meta)
-				*cp++ = '\033';
+		if (len == 1 && e->state & Mod1Mask)
+			*cp++ = '\033';
 
-			memcpy(cp, xstr, len);
-			len = cp - buf + len;
-			break;
-		}
+		memcpy(cp, xstr, len);
+		len = cp - buf + len;
 	}
 	ttywrite(buf, len);
 	if(IS_SET(MODE_ECHO))
-- 
1.7.10.4

>From f5957d6370fb34bc25db6f9cf8bab2a40ee13a47 Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Fri, 9 Nov 2012 10:52:10 +0100
Subject: Fix arrow keys terminfo capabilities

Usually the arrow keys generate the ANSI sequence which terminal will
understand like a movement, so it is not necessary any dealing for them, the
program can not know if the sequence is generate for a echo key or directly
from the program. If you need really know if the key was pressed then you
need activate the keypad mode where the keys will generate a special code
for each keypad key.

The terminfo capabilities kcub1, kcud1, kcuf1 and kcuu1 are used for this
keypad code, not for the sequence generate in the ansi mode.
---
 st.info |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/st.info b/st.info
index 63af234..199aff6 100644
--- a/st.info
+++ b/st.info
@@ -50,10 +50,10 @@ st| simpleterm,
 	is2=\E[4l\E>,
 	it#8,
 	kbs=\177,
-	kcub1=\E[D,
-	kcud1=\E[B,
-	kcuf1=\E[C,
-	kcuu1=\E[A,
+	kcub1=\EOD,
+	kcud1=\EOB,
+	kcuf1=\EOC,
+	kcuu1=\EOA,
 	kLFT=\E[d,
 	kRIT=\E[c,
 	kind=\E[a,
-- 
1.7.10.4

>From c8498f741fc9086ae7601c3fa091a2ef1d6035ab Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Mon, 12 Nov 2012 21:53:11 +0100
Subject: Add control and meta combinations for arrow keys

Since there isn't any terminfo capability for control and meta modifiers for
arrows keys it is necessary use the same that almost terminal emulators use,
because there are a lot of programs which have these codes hardcoded.

This cause also that shift combinations are also changed, but in this case
this is not a problem since there are terminfo capabilities for them. After
this patch shift-up and shift-down continue not working in emacs with
TERM=st, but they work with TERM=xterm, so it is possible some other changes
are necessary in the terminfo entry.
---
 config.def.h |   16 ++++++++++++----
 st.info      |    8 ++++----
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/config.def.h b/config.def.h
index 622499e..3d406d4 100644
--- a/config.def.h
+++ b/config.def.h
@@ -80,16 +80,24 @@ static Key key[] = {
 	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0,    0},
 	{ XK_Up,            XK_NO_MOD,      "\033[A",        0,   -1,    0},
 	{ XK_Up,            XK_NO_MOD,      "\033OA",        0,   +1,    0},
-	{ XK_Up,            ShiftMask,      "\033[a",        0,    0,    0},
+	{ XK_Up,            ShiftMask,      "\033[1;2A",     0,    0,    0},
+	{ XK_Up,            ControlMask,    "\033[1;5A",     0,    0,    0},
+	{ XK_Up,            Mod1Mask,       "\033[1;3A",     0,    0,    0},
 	{ XK_Down,          XK_NO_MOD,      "\033[B",        0,   -1,    0},
 	{ XK_Down,          XK_NO_MOD,      "\033OB",        0,   +1,    0},
-	{ XK_Down,          ShiftMask,      "\033[b",        0,    0,    0},
+	{ XK_Down,          ShiftMask,      "\033[1;2B",     0,    0,    0},
+	{ XK_Down,          ControlMask,    "\033[1;5B",     0,    0,    0},
+	{ XK_Down,          Mod1Mask,       "\033[1;3B",     0,    0,    0},
 	{ XK_Left,     	    XK_NO_MOD,      "\033[D",        0,   -1,    0},
 	{ XK_Left,          XK_NO_MOD,      "\033OD",        0,   +1,    0},
-	{ XK_Left,          ShiftMask,      "\033[d",        0,    0,    0},
+	{ XK_Left,          ShiftMask,      "\033[1;2D",     0,    0,    0},
+	{ XK_Left,          ControlMask,    "\033[1;5D",     0,    0,    0},
+	{ XK_Left,          Mod1Mask,       "\033[1;3D",     0,    0,    0},
 	{ XK_Right,         XK_NO_MOD,      "\033[C",        0,   -1,    0},
 	{ XK_Right,         XK_NO_MOD,      "\033OC",        0,   +1,    0},
-	{ XK_Right,         ShiftMask,      "\033[c",        0,    0,    0},
+	{ XK_Right,         ShiftMask,      "\033[1;2C",     0,    0,    0},
+	{ XK_Right,         ControlMask,    "\033[1;5C",     0,    0,    0},
+	{ XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0,    0},
 	{ XK_Return,        XK_NO_MOD,      "\n",            0,    0,   -1},
 	{ XK_Return,        XK_NO_MOD,      "\r\n",          0,    0,   +1},
 	{ XK_Return,        Mod1Mask,       "\033\n",        0,    0,   -1},
diff --git a/st.info b/st.info
index 199aff6..be2a47e 100644
--- a/st.info
+++ b/st.info
@@ -54,10 +54,10 @@ st| simpleterm,
 	kcud1=\EOB,
 	kcuf1=\EOC,
 	kcuu1=\EOA,
-	kLFT=\E[d,
-	kRIT=\E[c,
-	kind=\E[a,
-	kri=\E[b,
+	kLFT=\E[1;2D,
+	kRIT=\E[1;2C,
+	kind=\E[1;2B,
+	kri=\E[1;2A,
 	kdch1=\E[3~,
 	kich1=\E[2~,
 	kend=\E[4~,
-- 
1.7.10.4

>From b0b4ada3b4b560e4dacea4bd061e0df461dd948b Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <k...@shike2.com>
Date: Tue, 13 Nov 2012 12:57:12 +0100
Subject: Add missed key definitions

This patch adds the keys for the keypad (in both modes, application mode or
ansi mode) and function keys. It uses the same convention than xterm and
instead of using the XK_Fxx values it generates them using F1-F12 and
modifiers. For example:

   F1 -> ^[OP
   F1 + Shift = F13 -> ^[[1;2P
   F1 + Control = F25 -> ^[[1;5P
   F1 + Mod2 = F37 -> ^[[1;6P
   F1 + Mod1 = F49 -> ^[[1;3P
   F1 + Mod3 = F61 -> ^[[1;4P

It is also important notice than the terminfo capability kIC (shifted insert
key) only can be generated using the keypad keyboard, because the shorcut
for selection paste is using the same combination.

After this path the number of elements in the Key array becomes high, and
maybe a sequencial search is not enough efficient now.
---
 TODO         |    6 +---
 config.def.h |  102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 st.info      |   70 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 169 insertions(+), 9 deletions(-)

diff --git a/TODO b/TODO
index f56a6d9..e1168a1 100644
--- a/TODO
+++ b/TODO
@@ -5,11 +5,7 @@ vt emulation
 * color definition in CSI
 	* implement CSI parsing
 * make the keypad keys really work
-	* kf0 .. kf44
-	* kend, kel, kent, kfnd, ked, kext
-	* kNXT, kPRV
-	* ka1, ka3, kb2
-* add arrow keys handling
+	* kel, kfnd, ked, kext
 
 code & interface
 ----------------
diff --git a/config.def.h b/config.def.h
index 3d406d4..d6103b5 100644
--- a/config.def.h
+++ b/config.def.h
@@ -77,6 +77,49 @@ static unsigned int defaultucs = 257;
 /* key, mask, output, keypad, cursor, crlf */
 static Key key[] = {
 	/* keysym             mask         string         keypad cursor crlf */
+	{ XK_KP_Home,       XK_NO_MOD,      "\033[H",        0,    0,    0},
+	{ XK_KP_Home,       ShiftMask,      "\033[1;2H",     0,    0,    0},
+	{ XK_KP_Up,         XK_NO_MOD,      "\033Ox",       +1,    0,    0},
+	{ XK_KP_Up,         XK_NO_MOD,      "\033[A",        0,   -1,    0},
+	{ XK_KP_Up,         XK_NO_MOD,      "\033OA",        0,   +1,    0},
+	{ XK_KP_Down,       XK_NO_MOD,      "\033Or",       +1,    0,    0},
+	{ XK_KP_Down,       XK_NO_MOD,      "\033[B",        0,   -1,    0},
+	{ XK_KP_Down,       XK_NO_MOD,      "\033OB",        0,   +1,    0},
+	{ XK_KP_Left,       XK_NO_MOD,      "\033Ot",       +1,    0,    0},
+	{ XK_KP_Left,       XK_NO_MOD,      "\033[D",        0,   -1,    0},
+	{ XK_KP_Left,       XK_NO_MOD,      "\033OD",        0,   +1,    0},
+	{ XK_KP_Right,      XK_NO_MOD,      "\033Ov",       +1,    0,    0},
+	{ XK_KP_Right,      XK_NO_MOD,      "\033[C",        0,   -1,    0},
+	{ XK_KP_Right,      XK_NO_MOD,      "\033OC",        0,   +1,    0},
+	{ XK_KP_Prior,      XK_NO_MOD,      "\033[5~",	     0,    0,    0},
+	{ XK_KP_Prior,      ShiftMask,      "\033[5;2~",     0,    0,    0},
+	{ XK_KP_Begin,      XK_NO_MOD,      "\033[E",        0,    0,    0},
+	{ XK_KP_End,        XK_NO_MOD,      "\033[4~",       0,    0,    0},
+	{ XK_KP_End,        ShiftMask,      "\033[1;2F",     0,    0,    0},
+	{ XK_KP_Next,       XK_NO_MOD,      "\033[6~",       0,    0,    0},
+	{ XK_KP_Next,       ShiftMask,      "\033[6;2~",     0,    0,    0},
+	{ XK_KP_Insert,     XK_NO_MOD,      "\033[2~",       0,    0,    0},
+	{ XK_KP_Insert,     ShiftMask,      "\033[2;2~",     0,    0,    0},
+	{ XK_KP_Delete,     XK_NO_MOD,      "\033[3~",       0,    0,    0},
+	{ XK_KP_Delete,     ShiftMask,      "\033[3;2~",     0,    0,    0},
+	{ XK_KP_Multiply,   XK_NO_MOD,      "\033Oj",       +1,    0,    0},
+	{ XK_KP_Add,        XK_NO_MOD,      "\033Ok",       +1,    0,    0},
+	{ XK_KP_Enter,      XK_NO_MOD,      "\033OM",       +1,    0,    0},
+	{ XK_KP_Enter,      XK_NO_MOD,      "\n",           -1,    0,   -1},
+	{ XK_KP_Enter,      XK_NO_MOD,      "\r\n",         -1,    0,    0},
+	{ XK_KP_Subtract,   XK_NO_MOD,      "\033Om",       +1,    0,    0},
+	{ XK_KP_Decimal,    XK_NO_MOD,      "\033On",       +1,    0,    0},
+	{ XK_KP_Divide,     XK_NO_MOD,      "\033Oo",       +1,    0,    0},
+	{ XK_KP_0,          XK_NO_MOD,      "\033Op",       +1,    0,    0},
+	{ XK_KP_1,          XK_NO_MOD,      "\033Oq",       +1,    0,    0},
+	{ XK_KP_2,          XK_NO_MOD,      "\033Or",       +1,    0,    0},
+	{ XK_KP_3,          XK_NO_MOD,      "\033Os",       +1,    0,    0},
+	{ XK_KP_4,          XK_NO_MOD,      "\033Ot",       +1,    0,    0},
+	{ XK_KP_5,          XK_NO_MOD,      "\033Ou",       +1,    0,    0},
+	{ XK_KP_6,          XK_NO_MOD,      "\033Ov",       +1,    0,    0},
+	{ XK_KP_7,          XK_NO_MOD,      "\033Ow",       +1,    0,    0},
+	{ XK_KP_8,          XK_NO_MOD,      "\033Ox",       +1,    0,    0},
+	{ XK_KP_9,          XK_NO_MOD,      "\033Oy",       +1,    0,    0},
 	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0,    0},
 	{ XK_Up,            XK_NO_MOD,      "\033[A",        0,   -1,    0},
 	{ XK_Up,            XK_NO_MOD,      "\033OA",        0,   +1,    0},
@@ -98,28 +141,85 @@ static Key key[] = {
 	{ XK_Right,         ShiftMask,      "\033[1;2C",     0,    0,    0},
 	{ XK_Right,         ControlMask,    "\033[1;5C",     0,    0,    0},
 	{ XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0,    0},
+	{ XK_Tab,           ShiftMask,      "\033[Z",        0,    0,    0},
 	{ XK_Return,        XK_NO_MOD,      "\n",            0,    0,   -1},
 	{ XK_Return,        XK_NO_MOD,      "\r\n",          0,    0,   +1},
 	{ XK_Return,        Mod1Mask,       "\033\n",        0,    0,   -1},
 	{ XK_Return,        Mod1Mask,       "\033\r\n",      0,    0,   +1},
 	{ XK_Insert,        XK_NO_MOD,      "\033[2~",       0,    0,    0},
+	{ XK_Insert,        ShiftMask,      "\033[2;2~",     0,    0,    0},
 	{ XK_Delete,        XK_NO_MOD,      "\033[3~",       0,    0,    0},
-	{ XK_Home,          XK_NO_MOD,      "\033[1~",       0,    0,    0},
+	{ XK_Delete,        ShiftMask,      "\033[3;2~",     0,    0,    0},
+	{ XK_Home,          XK_NO_MOD,      "\033[H",        0,    0,    0},
+	{ XK_Home,          ShiftMask,      "\033[1;2H",     0,    0,    0},
 	{ XK_End,           XK_NO_MOD,      "\033[4~",       0,    0,    0},
+	{ XK_End,           ShiftMask,      "\033[1;2F",     0,    0,    0},
 	{ XK_Prior,         XK_NO_MOD,      "\033[5~",       0,    0,    0},
 	{ XK_Next,          XK_NO_MOD,      "\033[6~",       0,    0,    0},
+	{ XK_Next,          ShiftMask,      "\033[6;2~",     0,    0,    0},
 	{ XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0,    0},
+	{ XK_F1, /* F13 */  ShiftMask,      "\033[1;2P",     0,    0,    0},
+	{ XK_F1, /* F25 */  ControlMask,    "\033[1;5P",     0,    0,    0},
+	{ XK_F1, /* F37 */  Mod2Mask,       "\033[1;6P",     0,    0,    0},
+	{ XK_F1, /* F49 */  Mod1Mask,       "\033[1;3P",     0,    0,    0},
+	{ XK_F1, /* F61 */  Mod3Mask,       "\033[1;4P",     0,    0,    0},
 	{ XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0,    0},
+	{ XK_F2, /* F14 */  ShiftMask,      "\033[1;2Q",     0,    0,    0},
+	{ XK_F2, /* F26 */  ControlMask,    "\033[1;5Q",     0,    0,    0},
+	{ XK_F2, /* F38 */  Mod2Mask,       "\033[1;6Q",     0,    0,    0},
+	{ XK_F2, /* F50 */  Mod1Mask,       "\033[1;3Q",     0,    0,    0},
+	{ XK_F2, /* F62 */  Mod3Mask,       "\033[1;4Q",     0,    0,    0},
 	{ XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0,    0},
+	{ XK_F3, /* F15 */  ShiftMask,      "\033[1;2R",     0,    0,    0},
+	{ XK_F3, /* F27 */  ControlMask,    "\033[1;5R",     0,    0,    0},
+	{ XK_F3, /* F39 */  Mod2Mask,       "\033[1;6R",     0,    0,    0},
+	{ XK_F3, /* F51 */  Mod1Mask,       "\033[1;3R",     0,    0,    0},
+	{ XK_F3, /* F63 */  Mod3Mask,       "\033[1;4R",     0,    0,    0},
 	{ XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0,    0},
+	{ XK_F4, /* F16 */  ShiftMask,      "\033[1;2S",     0,    0,    0},
+	{ XK_F4, /* F28 */  ShiftMask,      "\033[1;5S",     0,    0,    0},
+	{ XK_F4, /* F40 */  Mod2Mask,       "\033[1;6S",     0,    0,    0},
+	{ XK_F4, /* F52 */  Mod1Mask,       "\033[1;3S",     0,    0,    0},
 	{ XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0,    0},
+	{ XK_F5, /* F17 */  ShiftMask,      "\033[15;2~",    0,    0,    0},
+	{ XK_F5, /* F29 */  ControlMask,    "\033[15;5~",    0,    0,    0},
+	{ XK_F5, /* F41 */  Mod2Mask,       "\033[15;6~",    0,    0,    0},
+	{ XK_F5, /* F53 */  Mod1Mask,       "\033[15;3~",    0,    0,    0},
 	{ XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0,    0},
+	{ XK_F6, /* F18 */  ShiftMask,      "\033[17;2~",    0,    0,    0},
+	{ XK_F6, /* F30 */  ControlMask,    "\033[17;5~",    0,    0,    0},
+	{ XK_F6, /* F42 */  Mod2Mask,       "\033[17;6~",    0,    0,    0},
+	{ XK_F6, /* F54 */  Mod1Mask,       "\033[17;3~",    0,    0,    0},
 	{ XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0,    0},
+	{ XK_F7, /* F19 */  ShiftMask,      "\033[18;2~",    0,    0,    0},
+	{ XK_F7, /* F31 */  ControlMask,    "\033[18;5~",    0,    0,    0},
+	{ XK_F7, /* F43 */  Mod2Mask,       "\033[18;6~",    0,    0,    0},
+	{ XK_F7, /* F55 */  Mod1Mask,       "\033[18;3~",    0,    0,    0},
 	{ XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0,    0},
+	{ XK_F8, /* F20 */  ShiftMask,      "\033[19;2~",    0,    0,    0},
+	{ XK_F8, /* F32 */  ControlMask,    "\033[19;5~",    0,    0,    0},
+	{ XK_F8, /* F44 */  Mod2Mask,       "\033[19;6~",    0,    0,    0},
+	{ XK_F8, /* F56 */  Mod1Mask,       "\033[19;3~",    0,    0,    0},
 	{ XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0,    0},
+	{ XK_F9, /* F21 */  ShiftMask,      "\033[20;2~",    0,    0,    0},
+	{ XK_F9, /* F33 */  ControlMask,    "\033[20;5~",    0,    0,    0},
+	{ XK_F9, /* F45 */  Mod2Mask,       "\033[20;6~",    0,    0,    0},
+	{ XK_F9, /* F57 */  Mod1Mask,       "\033[20;3~",    0,    0,    0},
 	{ XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0,    0},
+	{ XK_F10, /* F22 */ ShiftMask,      "\033[21;2~",    0,    0,    0},
+	{ XK_F10, /* F34 */ ControlMask,    "\033[21;5~",    0,    0,    0},
+	{ XK_F10, /* F46 */ Mod2Mask,       "\033[21;6~",    0,    0,    0},
+	{ XK_F10, /* F58 */ Mod1Mask,       "\033[21;3~",    0,    0,    0},
 	{ XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0,    0},
+	{ XK_F11, /* F23 */ ShiftMask,      "\033[23;2~",    0,    0,    0},
+	{ XK_F11, /* F35 */ ControlMask,    "\033[23;5~",    0,    0,    0},
+	{ XK_F11, /* F47 */ Mod2Mask,       "\033[23;6~",    0,    0,    0},
+	{ XK_F11, /* F59 */ Mod1Mask,       "\033[23;3~",    0,    0,    0},
 	{ XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0,    0},
+	{ XK_F12, /* F24 */ ShiftMask,      "\033[24;2~",    0,    0,    0},
+	{ XK_F12, /* F36 */ ControlMask,    "\033[24;5~",    0,    0,    0},
+	{ XK_F12, /* F48 */ Mod2Mask,       "\033[24;6~",    0,    0,    0},
+	{ XK_F12, /* F60 */ Mod1Mask,       "\033[24;3~",    0,    0,    0},
 };
 
 /* Internal shortcuts. */
diff --git a/st.info b/st.info
index be2a47e..4a05160 100644
--- a/st.info
+++ b/st.info
@@ -49,11 +49,24 @@ st| simpleterm,
 	invis=\E[8m,
 	is2=\E[4l\E>,
 	it#8,
+	ka1=\E[E,
+	ka3=\E[5~,
+	kc1=\E[4~,
+	kc3=\E[6~,
 	kbs=\177,
+	kcbt=\E[Z,
+	kb2=\EOu,
 	kcub1=\EOD,
 	kcud1=\EOB,
 	kcuf1=\EOC,
 	kcuu1=\EOA,
+	kDC=\E[3;2~,
+	kent=\EOM,
+	kEND=\E[1;2F,
+	kIC=\E[2;2~,
+	kNXT=\E[6;2~,
+	kPRV=\E[5;2~,
+	kHOM=\E[1;2H,
 	kLFT=\E[1;2D,
 	kRIT=\E[1;2C,
 	kind=\E[1;2B,
@@ -61,9 +74,6 @@ st| simpleterm,
 	kdch1=\E[3~,
 	kich1=\E[2~,
 	kend=\E[4~,
-	kf10=\E[21~,
-	kf11=\E[23~,
-	kf12=\E[24~,
 	kf1=\EOP,
 	kf2=\EOQ,
 	kf3=\EOR,
@@ -73,6 +83,60 @@ st| simpleterm,
 	kf7=\E[18~,
 	kf8=\E[19~,
 	kf9=\E[20~,
+	kf10=\E[21~,
+	kf11=\E[23~,
+	kf12=\E[24~,
+	kf13=\E[1;2P,
+	kf14=\E[1;2Q,
+	kf15=\E[1;2R,
+	kf16=\E[1;2S,
+	kf17=\E[15;2~,
+	kf18=\E[17;2~,
+	kf19=\E[18;2~,
+	kf20=\E[19;2~,
+	kf21=\E[20;2~,
+	kf22=\E[21;2~,
+	kf23=\E[23;2~,
+	kf24=\E[24;2~,
+	kf25=\E[1;5P,
+	kf26=\E[1;5Q,
+	kf27=\E[1;5R,
+	kf28=\E[1;5S,
+	kf29=\E[15;5~,
+	kf30=\E[17;5~,
+	kf31=\E[18;5~,
+	kf32=\E[19;5~,
+	kf33=\E[20;5~,
+	kf34=\E[21;5~,
+	kf35=\E[23;5~,
+	kf36=\E[24;5~,
+	kf37=\E[1;6P,
+	kf38=\E[1;6Q,
+	kf39=\E[1;6R,
+	kf40=\E[1;6S,
+	kf41=\E[15;6~,
+	kf42=\E[17;6~,
+	kf43=\E[18;6~,
+	kf44=\E[19;6~,
+	kf45=\E[20;6~,
+	kf46=\E[21;6~,
+	kf47=\E[23;6~,
+	kf48=\E[24;6~,
+	kf49=\E[1;3P,
+	kf50=\E[1;3Q,
+	kf51=\E[1;3R,
+	kf52=\E[1;3S,
+	kf53=\E[15;3~,
+	kf54=\E[17;3~,
+	kf55=\E[18;3~,
+	kf56=\E[19;3~,
+	kf57=\E[20;3~,
+	kf58=\E[21;3~,
+	kf59=\E[23;3~,
+	kf60=\E[24;3~,
+	kf61=\E[1;4P,
+	kf62=\E[1;4Q,
+	kf63=\E[1;4R,
 	khome=\E[1~,
 	knp=\E[6~,
 	kmous=\E[M,
-- 
1.7.10.4

Reply via email to