On Wed, Jan 04, 2023 at 08:08:48PM +0100, Paul de Weerd wrote:
> On Wed, Jan 04, 2023 at 02:33:57PM -0300, Crystal Kolipe wrote:
> | On Wed, Jan 04, 2023 at 04:42:55PM +0100, Paul de Weerd wrote:
> | > Hi Crystal,
> | >
> | > I tried your patch on my laptop. With it applied, and my TERM set to
> | > 'xterm', I do get colors in mutt and tmux.
> |
> | Great! Thanks for testing :).
> |
> | > The latter, however, shows
> | > '^@^@' before the PS1 prompt upon starting a new session (`tmux new`),
> | > behavior I don't see with a 'real' xterm.
> |
> | This looks like an off-by-one in the wscons code, (not introduced by me!)
> |
> | Does the following patch, (on top of the last one), fix it?
>
> Fixes only half of it: we're down to one ^@ now (which is not fixed
> with a s/1/2/ in your below diff).
Interestingly, I haven't been able to reproduce this, and when I tested it
originally I was only ever seeing one ^@, which was fixed by the previous
patch.
However, there is another similar off-by-one nearby, which I strongly suspect
is the culprit as fixing it makes the output of 'ESC [ c' more closely match
what a real xterm does.
I'm sending the complete diff again as anybody else testing the version from
this morning will definitely want these two new fixes. So back-out the
previous mini-patch and the main one before applying this.
Hopefully it'll fix the problem.
--- dev/wscons/wsemul_vt100_keys.c.dist Sat Mar 14 00:38:50 2015
+++ dev/wscons/wsemul_vt100_keys.c Mon Jan 2 16:01:42 2023
@@ -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:
@@ -174,14 +180,27 @@
case KS_KP_Next:
*out = "\033[6~";
return (4);
+ 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)
--- dev/wscons/wsemul_vt100_subr.c.dist Mon May 25 06:55:49 2020
+++ dev/wscons/wsemul_vt100_subr.c Wed Jan 4 16:46:43 2023
@@ -231,7 +231,7 @@
switch (A3(edp->modif1, edp->modif2, c)) {
case A3('>', '\0', 'c'): /* DA secondary */
wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID2,
- sizeof(WSEMUL_VT_ID2));
+ sizeof(WSEMUL_VT_ID2)-1);
break;
case A3('\0', '\0', 'J'): /* ED selective erase in display */
@@ -461,6 +461,9 @@
edp->ccol -= min(DEF1_ARG(0), edp->ccol);
edp->flags &= ~VTFL_LASTCHAR;
break;
+ case 'G': /* HPA */
+ edp->ccol = min(DEF1_ARG(0)-1, edp->ncols-1);
+ break;
case 'H': /* CUP */
case 'f': /* HVP */
if (edp->flags & VTFL_DECOM)
@@ -502,16 +505,37 @@
WSEMULOP(rc, edp, &edp->abortstate, erasecols,
ERASECOLS(NCOLS - n, n, edp->bkgdattr));
break;
+ case 'S': /* INDN */
+ wsemul_vt100_scrollup (edp,DEF1_ARG(0));
+ break;
+ case 'T': /* RIN */
+ wsemul_vt100_scrolldown (edp,DEF1_ARG(0));
+ break;
case 'X': /* ECH erase character */
n = min(DEF1_ARG(0), COLS_LEFT + 1);
WSEMULOP(rc, edp, &edp->abortstate, erasecols,
ERASECOLS(edp->ccol, n, edp->bkgdattr));
break;
+ case 'Z': /* KCBT */
+ if (!edp->ccol)
+ break;
+ if (edp->tabs) {
+ for (n=edp->ccol-1 ; n>0; n--)
+ if (edp->tabs[n])
+ break;
+ } else {
+ n=((edp->ccol - 1) & 8);
+ }
+ edp->ccol=n;
+ break;
case 'c': /* DA primary */
if (ARG(0) == 0)
wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID1,
- sizeof(WSEMUL_VT_ID1));
+ sizeof(WSEMUL_VT_ID1)-1);
break;
+ case 'd': /* VPA */
+ edp->crow = min(DEF1_ARG(0)-1, edp->nrows-1);
+ break;
case 'g': /* TBC */
if (edp->tabs != NULL)
switch (ARG(0)) {
@@ -549,6 +573,12 @@
case 1: /* bold */
flags |= WSATTR_HILIT;
break;
+ case 2: /* dim */
+ flags |= WSATTR_DIM;
+ break;
+ case 3: /* italic */
+ flags |= WSATTR_ITALIC;
+ break;
case 4: /* underline */
flags |= WSATTR_UNDERLINE;
break;
@@ -558,17 +588,43 @@
case 7: /* reverse */
flags |= WSATTR_REVERSE;
break;
- case 22: /* ~bold VT300 only */
+ /*
+ * Invisible text only makes the _glyph_ invisible.
+ *
+ * Other active attributes such as underlining and
+ * strikeout are still displayed in the character cell.
+ */
+ case 8: /* invisible */
+ flags |= WSATTR_INVISIBLE;
+ break;
+ case 9: /* strike */
+ flags |= WSATTR_STRIKE;
+ break;
+ case 21: /* double underline */
+ flags |= WSATTR_DOUBLE_UNDERLINE;
+ break;
+ case 22: /* ~bold ~dim VT300 only */
flags &= ~WSATTR_HILIT;
+ flags &= ~WSATTR_DIM;
break;
+ case 23: /* ~italic */
+ flags &= WSATTR_ITALIC;
+ break;
case 24: /* ~underline VT300 only */
flags &= ~WSATTR_UNDERLINE;
+ flags &= ~WSATTR_DOUBLE_UNDERLINE;
break;
case 25: /* ~blink VT300 only */
flags &= ~WSATTR_BLINK;
break;
case 27: /* ~reverse VT300 only */
flags &= ~WSATTR_REVERSE;
+ break;
+ case 28: /* ~invisible */
+ flags &= ~WSATTR_INVISIBLE;
+ break;
+ case 29: /* ~strike */
+ flags &= ~WSATTR_STRIKE;
break;
case 30: case 31: case 32: case 33:
case 34: case 35: case 36: case 37:
--- dev/wscons/wsksymdef.h.dist Mon Sep 20 14:32:39 2021
+++ dev/wscons/wsksymdef.h Mon Jan 2 15:48:18 2023
@@ -626,6 +626,7 @@
#define KS_Open 0xf393
#define KS_Paste 0xf394
#define KS_Cut 0xf395
+#define KS_Backtab 0xf396
#define KS_Menu 0xf3c0
#define KS_Pause 0xf3c1
--- dev/wscons/wsdisplayvar.h.dist Sun Sep 13 07:05:46 2020
+++ dev/wscons/wsdisplayvar.h Wed Jan 4 09:24:12 2023
@@ -94,11 +94,16 @@
#define WSCOL_CYAN 6
#define WSCOL_WHITE 7
/* flag values: */
-#define WSATTR_REVERSE 1
-#define WSATTR_HILIT 2
-#define WSATTR_BLINK 4
-#define WSATTR_UNDERLINE 8
-#define WSATTR_WSCOLORS 16
+#define WSATTR_REVERSE 1
+#define WSATTR_HILIT 2
+#define WSATTR_BLINK 4
+#define WSATTR_UNDERLINE 8
+#define WSATTR_WSCOLORS 16
+#define WSATTR_DIM 32
+#define WSATTR_STRIKE 64
+#define WSATTR_DOUBLE_UNDERLINE 128
+#define WSATTR_INVISIBLE 256
+#define WSATTR_ITALIC 512
};
#define WSSCREEN_NAME_SIZE 16
--- dev/pckbc/wskbdmap_mfii.c.dist Sat May 1 13:11:16 2021
+++ dev/pckbc/wskbdmap_mfii.c Mon Jan 2 13:51:12 2023
@@ -59,7 +59,7 @@
KC(12), KS_minus, KS_underscore,
KC(13), KS_equal, KS_plus,
KC(14), KS_Cmd_ResetEmul, KS_Delete,
- KC(15), KS_Tab,
+ KC(15), KS_Tab, KS_Backtab,
KC(16), KS_q,
KC(17), KS_w,
KC(18), KS_e,
@@ -103,16 +103,16 @@
KC(56), KS_Cmd2, KS_Alt_L,
KC(57), KS_space,
KC(58), KS_Caps_Lock,
- KC(59), KS_Cmd_Screen0, KS_f1,
- KC(60), KS_Cmd_Screen1, KS_f2,
- KC(61), KS_Cmd_Screen2, KS_f3,
- KC(62), KS_Cmd_Screen3, KS_f4,
- KC(63), KS_Cmd_Screen4, KS_f5,
- KC(64), KS_Cmd_Screen5, KS_f6,
- KC(65), KS_Cmd_Screen6, KS_f7,
- KC(66), KS_Cmd_Screen7, KS_f8,
- KC(67), KS_Cmd_Screen8, KS_f9,
- KC(68), KS_Cmd_Screen9, KS_f10,
+ KC(59), KS_Cmd_Screen0, KS_f1, KS_f13,
+ KC(60), KS_Cmd_Screen1, KS_f2, KS_f14,
+ KC(61), KS_Cmd_Screen2, KS_f3, KS_f15,
+ KC(62), KS_Cmd_Screen3, KS_f4, KS_f16,
+ KC(63), KS_Cmd_Screen4, KS_f5, KS_f17,
+ KC(64), KS_Cmd_Screen5, KS_f6, KS_f18,
+ KC(65), KS_Cmd_Screen6, KS_f7, KS_f19,
+ KC(66), KS_Cmd_Screen7, KS_f8, KS_f20,
+ KC(67), KS_Cmd_Screen8, KS_f9, KS_f21,
+ KC(68), KS_Cmd_Screen9, KS_f10, KS_f22,
KC(69), KS_Num_Lock,
KC(70), KS_Hold_Screen,
KC(71), KS_KP_Home, KS_KP_7,
@@ -128,8 +128,8 @@
KC(81), KS_KP_Next, KS_KP_3,
KC(82), KS_KP_Insert, KS_KP_0,
KC(83), KS_KP_Delete, KS_KP_Decimal,
- KC(87), KS_Cmd_Screen10, KS_f11,
- KC(88), KS_Cmd_Screen11, KS_f12,
+ KC(87), KS_Cmd_Screen10, KS_f11, KS_f23,
+ KC(88), KS_Cmd_Screen11, KS_f12, KS_f24,
KC(91), KS_f13,
KC(92), KS_f14,
KC(93), KS_f15,
--- dev/rasops/rasops.c.dist Thu Jul 23 06:17:03 2020
+++ dev/rasops/rasops.c Wed Jan 4 09:53:30 2023
@@ -141,7 +141,7 @@
uint32_t rs_defattr;
int rs_sbscreens;
-#define RS_SCROLLBACK_SCREENS 5
+#define RS_SCROLLBACK_SCREENS 20
int rs_dispoffset; /* rs_bs index, start of our actual screen */
int rs_visibleoffset; /* rs_bs index, current scrollback screen */
};
@@ -568,7 +568,19 @@
if ((flg & WSATTR_HILIT) != 0)
fg += 8;
- flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
+ /*
+ * The rapops code expects a different layout of the bitfields in flg:
+ *
+ * WSATTR_UNDERLINE is moved to bit 0
+ * Bits 1 and 2 are re-purposed to indicate whether the foreground and
+ * background are grey or not, (I.E. red==green==blue).
+ *
+ * This was probably a convenient hack when we only had to deal with
+ * underlining, but further attributes should maintain their original
+ * bit positions for consistency between the wscons and rasops code.
+ */
+
+ flg = ((flg & 0xfff8) | (flg & WSATTR_UNDERLINE ? 1 : 0));
if (rasops_isgray[fg])
flg |= 2;
--- dev/rasops/rasops32.c.dist Mon Jul 20 09:40:45 2020
+++ dev/rasops/rasops32.c Wed Jan 4 09:22:07 2023
@@ -93,11 +93,40 @@
b = ri->ri_devcmap[(attr >> 16) & 0xf];
f = ri->ri_devcmap[(attr >> 24) & 0xf];
+
+ /*
+ * Implement dim by shifting each of the red, green and blue values by
one bit.
+ *
+ * Since we are shifting each channel equally, this works for both RGB
and BGR as
+ * long as the values are stored in the lower 24 bits.
+ *
+ * XXX should we shift the upper 8 bits as well, to support devices
that work in
+ * 0xRRGGBBXX and 0xBBGGRRXX formats? Or will that break devices that
expect a
+ * special value in the high byte?
+ */
+
+ if ((attr & WSATTR_DIM)!=0) {
+ f=(f>>1) & 0x007F7F7F;
+ }
+
u.d[0][0] = b; u.d[0][1] = b;
u.d[1][0] = b; u.d[1][1] = f;
u.d[2][0] = f; u.d[2][1] = b;
u.d[3][0] = f; u.d[3][1] = f;
+ /*
+ * Implement 'invisible' attribute by changing the character to a space.
+ *
+ * We need to do this rather than just ignoring the character or filling
+ * the bits with 0x00 and returning as a special case, because effects
+ * such as underline and strikethrough are still rendered on invisible
+ * characters, (at least they are in xterm).
+ */
+
+ if ((attr & WSATTR_INVISIBLE)!=0) {
+ uc=' ';
+ }
+
if (uc == ' ') {
while (height--) {
/* the general, pixel-at-a-time case is fast enough */
@@ -202,12 +231,44 @@
}
}
+ /* Double underline relies on normal underlining being done as well. */
+
/* Do underline a pixel at a time */
- if ((attr & 1) != 0) {
+ if ((attr & (WSATTR_DOUBLE_UNDERLINE | 1)) != 0) {
rp -= step;
for (cnt = 0; cnt < width; cnt++)
((int *)rp)[cnt] = f;
}
+
+ /*
+ * Double underline now just needs to paint the second underline two
+ * rows up. */
+
+ if ((attr & WSATTR_DOUBLE_UNDERLINE)!=0) {
+ rp-=(step << 1);
+ for (cnt=0; cnt< width; cnt++)
+ ((int *)rp)[cnt]=f;
+ /*
+ * Reset row pointer to ensure that strikethough appears at a
+ * consistent height if combined with double underlining.
+ */
+
+ rp+=(step << 1);
+ }
+
+ /*
+ * Reset pointer to ensure that strikethough appears at a consistent
+ * height if combined with single underlining.
+ */
+
+ if ((attr & WSATTR_STRIKE)!=0) {
+ if ((attr & 1)==1) {
+ rp+=step ;
+ }
+ rp -= (1+ri->ri_font->fontheight/2)*step;
+ for (cnt=0; cnt< width; cnt++)
+ ((int *)rp)[cnt]=f;
+ }
return 0;
}