From ba9d0365ac7e138b643d7179457f8465a1dc1191 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Thu, 8 Nov 2012 17:17:26 +0100 Subject: [PATCH 01/16] Clarify some or exclusive expressions Since relational expresions are always evaluated to 0 or 1, we can use bitwise xor operator instead of using more complex boolean expressions. --- st.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) --- st.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/st.c b/st.c index 67fa790..9864442 100644 --- a/st.c +++ b/st.c @@ -1475,15 +1475,15 @@ tsetmode(bool priv, bool set, int *args, int narg) { break; case 1049: /* = 1047 and 1048 */ case 47: - case 1047: - if(IS_SET(MODE_ALTSCREEN)) + case 1047: { + bool alt = IS_SET(MODE_ALTSCREEN) != 0; + if(alt) tclearregion(0, 0, term.col-1, term.row-1); - if((set && !IS_SET(MODE_ALTSCREEN)) || - (!set && IS_SET(MODE_ALTSCREEN))) { + if(set ^ alt) /* set is always 1 or 0 */ tswapscreen(); - } if(*args != 1049) break; + } /* pass through */ case 1048: tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); @@ -2546,9 +2546,9 @@ drawregion(int x1, int y1, int x2, int y2) { int ic, ib, x, y, ox, sl; Glyph base, new; char buf[DRAW_BUF_SIZ]; - bool ena_sel = sel.bx != -1, alt = IS_SET(MODE_ALTSCREEN); + bool ena_sel = sel.bx != -1, alt = IS_SET(MODE_ALTSCREEN) != 0; - if((sel.alt && !alt) || (!sel.alt && alt)) + if((sel.alt != 0) ^ alt) ena_sel = 0; if(!(xw.state & WIN_VISIBLE)) return; -- 2.20.1 From ee3e0a9fd032bb35eea5c46fc0a9efcd6a80579a Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Thu, 8 Nov 2012 17:20:15 +0100 Subject: [PATCH 02/16] Save cursor position in terminal reset After terminal reset saved terminal position is reset to 0, allowing know where cursor will go in next restore cursor operation. --- st.c | 2 ++ 1 file changed, 2 insertions(+) --- st.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/st.c b/st.c index 9864442..4a77d71 100644 --- a/st.c +++ b/st.c @@ -1076,6 +1076,8 @@ treset(void) { term.mode = MODE_WRAP; tclearregion(0, 0, term.col-1, term.row-1); + tmoveto(0, 0); + tcursor(CURSOR_SAVE); } void -- 2.20.1 From 5260a9ea2249b9159c188a6e27a39a38d131e411 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Thu, 8 Nov 2012 17:21:10 +0100 Subject: [PATCH 03/16] Add DECOM sequence DECOM sequence allows to the user defines a new home position. The home position is used as base for all the movement commands except HVP and VPA. It is important notice than DECSLM moves cursor to absolute position 0,0. --- st.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) --- st.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/st.c b/st.c index 4a77d71..657fba7 100644 --- a/st.c +++ b/st.c @@ -97,6 +97,7 @@ enum cursor_movement { enum cursor_state { CURSOR_DEFAULT = 0, CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 }; enum glyph_state { @@ -300,6 +301,7 @@ static void tdeleteline(int); static void tinsertblank(int); static void tinsertblankline(int); static void tmoveto(int, int); +static void tmoveato(int x, int y); static void tnew(int, int); static void tnewline(int); static void tputtab(bool); @@ -1211,10 +1213,25 @@ csiparse(void) { } } +/* for absolute user moves, when decom is set */ +void +tmoveato(int x, int y) { + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); +} + void tmoveto(int x, int y) { + int miny, maxy; + + if(term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } LIMIT(x, 0, term.col-1); - LIMIT(y, 0, term.row-1); + LIMIT(y, miny, maxy); term.c.state &= ~CURSOR_WRAPNEXT; term.c.x = x; term.c.y = y; @@ -1456,7 +1473,9 @@ tsetmode(bool priv, bool set, int *args, int narg) { if(mode != term.mode) redraw(); break; - case 6: /* XXX: DECOM -- Origin */ + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); break; case 7: /* DECAWM -- Auto wrap */ MODBIT(term.mode, set, MODE_WRAP); @@ -1593,7 +1612,7 @@ csihandle(void) { case 'f': /* HVP */ DEFAULT(csiescseq.arg[0], 1); DEFAULT(csiescseq.arg[1], 1); - tmoveto(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); break; case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ DEFAULT(csiescseq.arg[0], 1); @@ -1667,7 +1686,7 @@ csihandle(void) { break; case 'd': /* VPA -- Move to */ DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, csiescseq.arg[0]-1); + tmoveato(term.c.x, csiescseq.arg[0]-1); break; case 'h': /* SM -- Set terminal mode */ tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); @@ -1682,7 +1701,7 @@ csihandle(void) { DEFAULT(csiescseq.arg[0], 1); DEFAULT(csiescseq.arg[1], term.row); tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveto(0, 0); + tmoveato(0, 0); } break; case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ @@ -2119,10 +2138,10 @@ tresize(int col, int row) { /* update terminal size */ term.col = col; term.row = row; - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); /* reset scrolling region */ tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); return (slide > 0); } -- 2.20.1 From d5b80e05e8df29b989c072b6529745576056d0bc Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Thu, 8 Nov 2012 17:21:24 +0100 Subject: [PATCH 04/16] Fix VPR sequence VPR stands for Move cursor down a number of rows, and the code was moving the cursor up instead of moving it down. --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 657fba7..f67a345 100644 --- a/st.c +++ b/st.c @@ -1562,11 +1562,11 @@ csihandle(void) { tinsertblank(csiescseq.arg[0]); break; case 'A': /* CUU -- Cursor Up */ - case 'e': DEFAULT(csiescseq.arg[0], 1); tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); break; case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ DEFAULT(csiescseq.arg[0], 1); tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); break; @@ -1575,7 +1575,7 @@ csihandle(void) { ttywrite(VT102ID, sizeof(VT102ID) - 1); break; case 'C': /* CUF -- Cursor Forward */ - case 'a': + case 'a': /* HPR -- Cursor Forward */ DEFAULT(csiescseq.arg[0], 1); tmoveto(term.c.x+csiescseq.arg[0], term.c.y); break; -- 2.20.1 From 27468403cc436cf8197c886158e6e61f24ae5b8d Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Thu, 8 Nov 2012 17:21:41 +0100 Subject: [PATCH 05/16] Ignore DECARM sequence DECARM modify the auto repeat settings in the keyboard, and since we can not modify this setting in the Xserver the best solution is only ignore it. --- st.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- st.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/st.c b/st.c index f67a345..5e7e4ac 100644 --- a/st.c +++ b/st.c @@ -1480,8 +1480,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { case 7: /* DECAWM -- Auto wrap */ MODBIT(term.mode, set, MODE_WRAP); break; - case 8: /* XXX: DECARM -- Auto repeat */ - break; + case 8: /* DECARM -- Auto repeat (IGNORED) */ case 0: /* Error (IGNORED) */ case 12: /* att610 -- Start blinking cursor (IGNORED) */ break; -- 2.20.1 From 866590521609ba35606e53990e381bdc2adf742f Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Thu, 8 Nov 2012 17:22:04 +0100 Subject: [PATCH 06/16] Move unsupported sequences to ignored. These sequences will be never implemented and in this moment they are generating a lot of noise. --- st.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) --- st.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/st.c b/st.c index 5e7e4ac..8059b16 100644 --- a/st.c +++ b/st.c @@ -1480,8 +1480,14 @@ tsetmode(bool priv, bool set, int *args, int narg) { case 7: /* DECAWM -- Auto wrap */ MODBIT(term.mode, set, MODE_WRAP); break; - case 8: /* DECARM -- Auto repeat (IGNORED) */ case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ case 12: /* att610 -- Start blinking cursor (IGNORED) */ break; case 25: /* DECTCEM -- Text Cursor Enable Mode */ @@ -1509,12 +1515,6 @@ tsetmode(bool priv, bool set, int *args, int narg) { tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); break; default: - /* case 2: DECANM -- ANSI/VT52 (NOT SUPPOURTED) */ - /* case 3: DECCOLM -- Column (NOT SUPPORTED) */ - /* case 4: DECSCLM -- Scroll (NOT SUPPORTED) */ - /* case 18: DECPFF -- Printer feed (NOT SUPPORTED) */ - /* case 19: DECPEX -- Printer extent (NOT SUPPORTED) */ - /* case 42: DECNRCM -- National characters (NOT SUPPORTED) */ fprintf(stderr, "erresc: unknown private set/reset mode %d\n", *args); -- 2.20.1 From 5d5a7c627a3709c3758c516de87609bb6b518e13 Mon Sep 17 00:00:00 2001 From: Christoph Lohmann <20h@r-36.net> Date: Thu, 8 Nov 2012 17:22:48 +0100 Subject: [PATCH 07/16] Moving the alt declaration to the beginning of the function. --- st.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index 8059b16..2919082 100644 --- a/st.c +++ b/st.c @@ -1459,6 +1459,7 @@ tsetscroll(int t, int b) { void tsetmode(bool priv, bool set, int *args, int narg) { int *lim, mode; + bool alt; for(lim = args + narg; args < lim; ++args) { if(priv) { @@ -1502,7 +1503,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { case 1049: /* = 1047 and 1048 */ case 47: case 1047: { - bool alt = IS_SET(MODE_ALTSCREEN) != 0; + alt = IS_SET(MODE_ALTSCREEN) != 0; if(alt) tclearregion(0, 0, term.col-1, term.row-1); if(set ^ alt) /* set is always 1 or 0 */ -- 2.20.1 From c4a9ccec19b14a6bdc980d149e2c27c30f250945 Mon Sep 17 00:00:00 2001 From: Christoph Lohmann <20h@r-36.net> Date: Sun, 11 Nov 2012 19:38:41 +0100 Subject: [PATCH 08/16] Removing some xft naming cruft. --- st.c | 82 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/st.c b/st.c index 2919082..c043e3f 100644 --- a/st.c +++ b/st.c @@ -28,8 +28,12 @@ #include #include #include + #define Glyph Glyph_ #define Font Font_ +#define Draw XftDraw * +#define Colour XftColor +#define Colourmap Colormap #if defined(__linux) #include @@ -198,14 +202,14 @@ typedef struct { /* Purely graphic info */ typedef struct { - Display* dpy; - Colormap cmap; + Display *dpy; + Colourmap cmap; Window win; XdbeBackBuffer buf; Atom xembed, wmdeletewin; XIM xim; XIC xic; - XftDraw *xft_draw; + Draw draw; Visual *vis; int scr; bool isfixed; /* is fixed geometry? */ @@ -267,12 +271,12 @@ typedef struct { int descent; short lbearing; short rbearing; - XftFont *xft_set; + XftFont *set; } Font; /* Drawing Context */ typedef struct { - XftColor xft_col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; + Colour col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; GC gc; Font font, bfont, ifont, ibfont; } DC; @@ -2151,19 +2155,19 @@ xresize(int col, int row) { xw.tw = MAX(1, 2*borderpx + col * xw.cw); xw.th = MAX(1, 2*borderpx + row * xw.ch); - XftDrawChange(xw.xft_draw, xw.buf); + XftDrawChange(xw.draw, xw.buf); } void xloadcols(void) { int i, r, g, b; - XRenderColor xft_color = { .alpha = 0 }; + XRenderColor color = { .alpha = 0 }; /* load colors [0-15] colors and [256-LEN(colorname)[ (config.h) */ for(i = 0; i < LEN(colorname); i++) { if(!colorname[i]) continue; - if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, colorname[i], &dc.xft_col[i])) { + if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, colorname[i], &dc.col[i])) { die("Could not allocate color '%s'\n", colorname[i]); } } @@ -2172,10 +2176,10 @@ xloadcols(void) { for(i = 16, r = 0; r < 6; r++) { for(g = 0; g < 6; g++) { for(b = 0; b < 6; b++) { - xft_color.red = r == 0 ? 0 : 0x3737 + 0x2828 * r; - xft_color.green = g == 0 ? 0 : 0x3737 + 0x2828 * g; - xft_color.blue = b == 0 ? 0 : 0x3737 + 0x2828 * b; - if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &xft_color, &dc.xft_col[i])) { + color.red = r == 0 ? 0 : 0x3737 + 0x2828 * r; + color.green = g == 0 ? 0 : 0x3737 + 0x2828 * g; + color.blue = b == 0 ? 0 : 0x3737 + 0x2828 * b; + if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i])) { die("Could not allocate color %d\n", i); } i++; @@ -2184,9 +2188,9 @@ xloadcols(void) { } for(r = 0; r < 24; r++, i++) { - xft_color.red = xft_color.green = xft_color.blue = 0x0808 + 0x0a0a * r; - if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &xft_color, - &dc.xft_col[i])) { + color.red = color.green = color.blue = 0x0808 + 0x0a0a * r; + if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, + &dc.col[i])) { die("Could not allocate color %d\n", i); } } @@ -2194,8 +2198,8 @@ xloadcols(void) { void xtermclear(int col1, int row1, int col2, int row2) { - XftDrawRect(xw.xft_draw, - &dc.xft_col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], + XftDrawRect(xw.draw, + &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], borderpx + col1 * xw.cw, borderpx + row1 * xw.ch, (col2-col1+1) * xw.cw, @@ -2207,8 +2211,8 @@ xtermclear(int col1, int row1, int col2, int row2) { */ void xclear(int x1, int y1, int x2, int y2) { - XftDrawRect(xw.xft_draw, - &dc.xft_col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], + XftDrawRect(xw.draw, + &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], x1, y1, x2-x1, y2-y1); } @@ -2245,17 +2249,17 @@ xloadfont(Font *f, FcPattern *pattern) { match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); if(!match) return 1; - if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { + if(!(f->set = XftFontOpenPattern(xw.dpy, match))) { FcPatternDestroy(match); return 1; } - f->ascent = f->xft_set->ascent; - f->descent = f->xft_set->descent; + f->ascent = f->set->ascent; + f->descent = f->set->descent; f->lbearing = 0; - f->rbearing = f->xft_set->max_advance_width; + f->rbearing = f->set->max_advance_width; - f->height = f->xft_set->height; + f->height = f->set->height; f->width = f->lbearing + f->rbearing; return 0; @@ -2365,8 +2369,8 @@ xinit(void) { xw.fy = 0; } - attrs.background_pixel = dc.xft_col[defaultbg].pixel; - attrs.border_pixel = dc.xft_col[defaultbg].pixel; + attrs.background_pixel = dc.col[defaultbg].pixel; + attrs.border_pixel = dc.col[defaultbg].pixel; attrs.bit_gravity = NorthWestGravity; attrs.event_mask = FocusChangeMask | KeyPressMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask @@ -2387,7 +2391,7 @@ xinit(void) { xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeCopied); /* Xft rendering context */ - xw.xft_draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); /* input methods */ xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); @@ -2420,20 +2424,20 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { width = charlen * xw.cw; Font *font = &dc.font; XGlyphInfo extents; - XftColor *fg = &dc.xft_col[base.fg], *bg = &dc.xft_col[base.bg], + Colour *fg = &dc.col[base.fg], *bg = &dc.col[base.bg], *temp, revfg, revbg; XRenderColor colfg, colbg; if(base.mode & ATTR_BOLD) { if(BETWEEN(base.fg, 0, 7)) { /* basic system colors */ - fg = &dc.xft_col[base.fg + 8]; + fg = &dc.col[base.fg + 8]; } else if(BETWEEN(base.fg, 16, 195)) { /* 256 colors */ - fg = &dc.xft_col[base.fg + 36]; + fg = &dc.col[base.fg + 36]; } else if(BETWEEN(base.fg, 232, 251)) { /* greyscale */ - fg = &dc.xft_col[base.fg + 4]; + fg = &dc.col[base.fg + 4]; } /* * Those ranges will not be brightened: @@ -2450,8 +2454,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { font = &dc.ibfont; if(IS_SET(MODE_REVERSE)) { - if(fg == &dc.xft_col[defaultfg]) { - fg = &dc.xft_col[defaultbg]; + if(fg == &dc.col[defaultfg]) { + fg = &dc.col[defaultbg]; } else { colfg.red = ~fg->color.red; colfg.green = ~fg->color.green; @@ -2461,8 +2465,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { fg = &revfg; } - if(bg == &dc.xft_col[defaultbg]) { - bg = &dc.xft_col[defaultfg]; + if(bg == &dc.col[defaultbg]) { + bg = &dc.col[defaultfg]; } else { colbg.red = ~bg->color.red; colbg.green = ~bg->color.green; @@ -2476,7 +2480,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { if(base.mode & ATTR_REVERSE) temp = fg, fg = bg, bg = temp; - XftTextExtentsUtf8(xw.dpy, font->xft_set, (FcChar8 *)s, bytelen, + XftTextExtentsUtf8(xw.dpy, font->set, (FcChar8 *)s, bytelen, &extents); width = extents.xOff; @@ -2494,12 +2498,12 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { if(y == term.row-1) xclear(winx, winy + xw.ch, winx + width, xw.h); - XftDrawRect(xw.xft_draw, bg, winx, winy, width, xw.ch); - XftDrawStringUtf8(xw.xft_draw, fg, font->xft_set, winx, + XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch); + XftDrawStringUtf8(xw.draw, fg, font->set, winx, winy + font->ascent, (FcChar8 *)s, bytelen); if(base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.xft_draw, fg, winx, winy + font->ascent + 1, + XftDrawRect(xw.draw, fg, winx, winy + font->ascent + 1, width, 1); } } -- 2.20.1 From ace789a79fc44c1c3b629f5c0fb477c651d84a48 Mon Sep 17 00:00:00 2001 From: Christoph Lohmann <20h@r-36.net> Date: Sun, 11 Nov 2012 19:46:34 +0100 Subject: [PATCH 09/16] Gc is not used anymore. --- st.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/st.c b/st.c index c043e3f..8b18607 100644 --- a/st.c +++ b/st.c @@ -277,7 +277,6 @@ typedef struct { /* Drawing Context */ typedef struct { Colour col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; - GC gc; Font font, bfont, ifont, ibfont; } DC; @@ -2398,8 +2397,6 @@ xinit(void) { xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); - /* gc */ - dc.gc = XCreateGC(xw.dpy, xw.win, 0, NULL); /* white cursor, black outline */ cursor = XCreateFontCursor(xw.dpy, XC_xterm); -- 2.20.1 From 73177ba366e5363b8a6695882b52617a8909a925 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:04:26 +0100 Subject: [PATCH 10/16] Add SRM sequence This sequence enable/disable the local echo. --- st.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 20 deletions(-) --- 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); @@ -1848,6 +1851,28 @@ tputtab(bool forward) { tmoveto(x, term.c.y); } +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; @@ -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 -- 2.20.1 From 69ee3ba3a771ca60bc8738174c79fc851818a36b Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:04:34 +0100 Subject: [PATCH 11/16] 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(-) --- 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, -- 2.20.1 From 93f31166bfff317e050dde1723cfa8302c6f85d3 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:04:39 +0100 Subject: [PATCH 12/16] 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(-) --- 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) -- 2.20.1 From ea782bfc5d34d712bc9391e498935d2d27f3116c Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:04:45 +0100 Subject: [PATCH 13/16] 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(-) --- 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)) -- 2.20.1 From 3b16695f4e8a29f47ad273912065dfba53544a29 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:04:50 +0100 Subject: [PATCH 14/16] 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(-) --- 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, -- 2.20.1 From 44597b359e030d86e16ab9b6510f54366d57e5ac Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:04:54 +0100 Subject: [PATCH 15/16] 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(-) --- 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~, -- 2.20.1 From 620e3bb39ebe617b69b5cb1323b4f47c2f699527 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Tue, 13 Nov 2012 20:05:02 +0100 Subject: [PATCH 16/16] 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(-) --- 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, -- 2.20.1