Index | Thread | Search

From:
Crystal Kolipe <kolipe.c@exoticsilicon.com>
Subject:
Re: Make wscons F1 - F4 match xterm, (and fix vt220 breakage)
To:
tech@openbsd.org
Date:
Thu, 26 Jun 2025 04:18:43 -0300

Download raw body.

Thread
Ping?

Keys F1 - F4 keys have never worked correctly when using the default vt220
emulation on wscons.

Since the future is clearly TERM=xterm and no longer TERM=pccon we really want
this.

This mis-match between what vt220/xterm expects and what wscons provides hurts
even the most basic usage of the wscons console:

Fresh OpenBSD install, (any version).  Install mutt from ports.  Press F1.
Manual does not appear.  Start X11, start mutt in an xterm, press F1, manual
appears.

On Tue, Jun 10, 2025 at 03:57:49PM -0300, Crystal Kolipe wrote:
> This patch changes the sequences sent by wscons for F1 - F4 to match xterm.
> 
> There are also changes for F13 - F24, begin, home, and end.
> 
> 
> Rationale:
> 
> The default wscons termtype is vt220.  By default, programs that use terminfo
> are broken on the console, because F1 - F4 are not recognised.
> 
> Sequences currently sent for F1 - F4 are: ^[[11~, ^[[12~, ^[[13~, and ^[[14~.
> 
> The vt220 emulation expects ^[OP, ^[OQ, ^[OR, and ^[OS.
> 
> The xterm terminfo entry also expects ^[OP, ^[OQ, ^[OR, and ^[OS.
> 
> Although the current sequences work with 'pccon', the pccon terminfo entry is
> broken in various ways with respect to current wscons behaviour.
> 
> Furthermore, with the various improvements to wscons over the last few
> releases, compatibility with the various xterm typetypes is now much better
> than basically anything else, (including vt220).
> 
> --- wsemul_vt100_keys.c
> +++ wsemul_vt100_keys.c
> @@ -37,11 +37,9 @@
>  #include <dev/wscons/wsemulvar.h>
>  #include <dev/wscons/wsemul_vt100var.h>
>  
> +#define vt100_fkeys_len(x) (5 + (x >= 8) + (x >= 12))
> +
>  static const u_char *vt100_fkeys[] = {
> -	"\033[11~",	/* F1 */
> -	"\033[12~",
> -	"\033[13~",		/* F1-F5 normally don't send codes */
> -	"\033[14~",
>  	"\033[15~",	/* F5 */
>  	"\033[17~",	/* F6 */
>  	"\033[18~",
> @@ -50,18 +48,18 @@
>  	"\033[21~",
>  	"\033[23~",	/* VT100: ESC */
>  	"\033[24~",	/* VT100: BS */
> -	"\033[25~",	/* VT100: LF */
> -	"\033[26~",
> -	"\033[28~",	/* help */
> -	"\033[29~",	/* do */
> -	"\033[31~",
> -	"\033[32~",
> -	"\033[33~",
> -	"\033[34~",	/* F20 */
> -	"\033[35~",
> -	"\033[36~",
> -	"\033[37~",
> -	"\033[38~"
> +	"\033[1;2P",	/* VT100: LF */
> +	"\033[1;2Q",
> +	"\033[1;2R",	/* help */
> +	"\033[1;2S",	/* do */
> +	"\033[15;2~",
> +	"\033[17;2~",
> +	"\033[18;2~",
> +	"\033[19;2~",	/* F20 */
> +	"\033[20;2~",
> +	"\033[21;2~",
> +	"\033[23;2~",
> +	"\033[24;2~"
>  };
>  
>  static const u_char *vt100_pfkeys[] = {
> @@ -96,14 +94,22 @@
>  		    edp->translatebuf, edp->flags & VTFL_UTF8));
>  	}
>  
> -	if (in >= KS_f1 && in <= KS_f24) {
> -		*out = vt100_fkeys[in - KS_f1];
> -		return (5);
> +	if (in >= KS_f1 && in <= KS_f4) {
> +		*out = vt100_pfkeys[in - KS_f1];
> +		return (3);
>  	}
> -	if (in >= KS_F1 && in <= KS_F24) {
> -		*out = vt100_fkeys[in - KS_F1];
> -		return (5);
> +	if (in >= KS_F1 && in <= KS_F4) {
> +		*out = vt100_pfkeys[in - KS_F1];
> +		return (3);
>  	}
> +	if (in >= KS_f5 && in <= KS_f24) {
> +		*out = vt100_fkeys[in - KS_f5];
> +		return vt100_fkeys_len(in - KS_f5);
> +	}
> +	if (in >= KS_F5 && in <= KS_F24) {
> +		*out = vt100_fkeys[in - KS_F5];
> +		return vt100_fkeys_len(in - KS_F5);
> +	}
>  	if (in >= KS_KP_F1 && in <= KS_KP_F4) {
>  		*out = vt100_pfkeys[in - KS_KP_F1];
>  		return (3);
> @@ -148,12 +154,12 @@
>  	}
>  	switch (in) {
>  	    case KS_Help:
> -		*out = vt100_fkeys[15 - 1];
> +		*out = vt100_fkeys[15 - 1 + 4]; /* vt100_fkeys starts at F5 */
>  		return (5);
>  	    case KS_Execute: /* "Do" */
> -		*out = vt100_fkeys[16 - 1];
> +		*out = vt100_fkeys[16 - 1 + 4]; /* vt100_fkeys starts at F5 */
>  		return (5);
> -	    case KS_Find:
> +	    case KS_Find:			/* Not defined in xterm terminfo */
>  		*out = "\033[1~";
>  		return (4);
>  	    case KS_Insert:
> @@ -163,7 +169,7 @@
>  	    case KS_KP_Delete:
>  		*out = "\033[3~";
>  		return (4);
> -	    case KS_Select:
> +	    case KS_Select:			/* Not defined in xterm terminfo */
>  		*out = "\033[4~";
>  		return (4);
>  	    case KS_Prior:
> @@ -177,14 +183,24 @@
>  	    case KS_Backtab:
>  		*out = "\033[Z";
>  		return (3);
> +	    /*
> +	     * Unlike insert, delete, page up, and page down, we purposely don't
> +	     * send the same sequence of \033OE for the non-keypad 'begin' key.
> +	     *
> +	     * This is because the terminfo xterm entry is mapping this to kb2,
> +	     * which is defined as 'centre of keypad'.
> +	     */
> +	    case KS_KP_Begin:
> +		*out = "\033OE";
> +		return (3);
>  	    case KS_Home:
>  	    case KS_KP_Home:
> -		*out = "\033[7~";
> -		return (4);
> +		*out = "\033OH";
> +		return (3);
>  	    case KS_End:
>  	    case KS_KP_End:
> -		*out = "\033[8~";
> -		return (4);
> +		*out = "\033OF";
> +		return (3);
>  	    case KS_Up:
>  	    case KS_KP_Up:
>  		if (edp->flags & VTFL_APPLCURSOR)
>