On Sat, Jan 07, 2023 at 09:05:21AM -0300, Crystal Kolipe wrote:
> In any case, I'll post an updated version with 256 in an hour or so.

It's here!

NEW - 256 colour support!  (Not extensively tested yet).
NEW - Interpret SGR 38/48 sequences instead of just discarding the following
      parameters.
NEW - Implement SGR 9x and 10x sequences to select 'bright' foreground and
      background colours, (I.E. colours 8 - 15), directly.
    - All the features of the previous patches.

So this version is mostly to add 256 colour support.  This was mainly a
consequence of needing to do something with SGR 38/48 in order to avoid
programs that use them directly setting unwanted attributes.

Resume of code changes:

* Adds a new WSSCREEN_256COL capability which is currently set for 32bpp
  displays only.

* When running in 32bpp, the device colour map is re-programmed for colours
  16 - 255.

* Several 4-bit fields have been expanded to 8-bit.

* Resizes ri_devcmap from 16 to 256 entries.

* Bold, which is implemented as higher intensity, is limited to the eight
  'normal' colours.  (This might change in a later version.)

Notes:

* Please test for regressions and breakage.

* The plain 'xterm' terminfo entry doesn't support 256 colours, so you
  probably want to use TERM=xterm-256color instead.

* However testing with plain TERM=xterm is definitely still needed!

* Programs that ignore terminfo and send ansi sequences directly will also
  benefit from testing.

Question:

There is a comment in rasops.c saying that the last 16 colours should be the
inverse of the first 16.  However, from reading the code this seems to apply
only if we are both using a palletised display _and_ using rasops_do_cursor
instead of rasops_wronly_do_cursor.

(The comment pre-dates the addition of rasops_wronly_do_cursor by many years.)

Or have I missed something?  Should I update the comment?

--- 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      Sat Jan  7 09:52:11 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,11 +588,31 @@
                        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;
@@ -570,12 +620,84 @@
                        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:
                                /* fg color */
                                flags |= WSATTR_WSCOLORS;
                                fgcol = ARG(n) - 30;
                                break;
+                       /*
+                        * Some software naively assumes that sequences such
+                        * as CSI 38;5;Xm are available without really
+                        * checking the terminal capabilities.
+                        *
+                        * If we don't swallow the parameters following the
+                        * 38, they get incorrectly interpreted as 'CSI m'
+                        * sequences on their own.
+                        *
+                        * So an attempt to set colour 1 ends up setting bold
+                        * and blink, because wscons treats CSI 38;5;1m as
+                        * CSI 5;1m.
+                        *
+                        * A similar problem exists for CSI 48m sequences.
+                        */
+#define EXIST_ARG2(i) ((edp->nargs-n)>=3)
+#define ARG2_OR_DEF(i) (EXIST_ARG2(i) ? ARG(i+2) : 0)
+                       case 38:
+                               /*
+                                * 38 followed by zero arguments is meaningless.
+                                */
+                               if (edp->nargs == n+1) {
+                                       break ;
+                               }
+                               /*
+                                * 5 should normally be followed by a single
+                                * argument, but zero arguments is also valid to
+                                * set colour zero.
+                                */
+                               if (ARG(n+1)==5) {
+                                       flags |= WSATTR_WSCOLORS;
+                                       if (edp->scrcapabilities &
+                                           WSSCREEN_256COL) {
+                                               fgcol = ARG2_OR_DEF(n);
+                                               } else {
+                                               fgcol = (ARG2_OR_DEF(n) < 8 ? 
ARG2_OR_DEF(n)
+                                                   : fgcol );
+                                               }
+                                       n+=(EXIST_ARG2(n) ? 2 : 1);
+                                       break;
+                               }
+                               /*
+                                * 2 should introduce a sequence of three
+                                * arguments, specifying RGB.
+                                *
+                                * We don't, (yet!), support setting colours by
+                                * 24-bit RGB arguments and don't want to
+                                * interpret these as regular SGR codes.
+                                *
+                                * If there are more then three, skip just
+                                * three, otherwise skip all of them.
+                                */
+                               if (ARG(n+1)==2) {
+                                       n=(edp->nargs-n > 5 ? n+4 :
+                                           edp->nargs);
+                                       break;
+                               }
+                               /*
+                                * Invalid code, I.E. not 2 or 5.
+                                *
+                                * We do what xterm does and just skip the
+                                * single unrecognised argument, then allow any
+                                * following arguments to be interpreted as SGR.
+                                */
+                               n++;
+                               break;
                        case 39:
                                /* reset fg color */
                                fgcol = WSCOL_WHITE;
@@ -588,11 +710,46 @@
                                flags |= WSATTR_WSCOLORS;
                                bgcol = ARG(n) - 40;
                                break;
+                       case 48:
+                               if (edp->nargs == n+1) {
+                                       break ;
+                               }
+                               if (ARG(n+1)==5) {
+                                       flags |= WSATTR_WSCOLORS;
+                                       if (edp->scrcapabilities &
+                                           WSSCREEN_256COL) {
+                                               bgcol = ARG2_OR_DEF(n);
+                                               } else {
+                                               bgcol = (ARG2_OR_DEF(n) < 8 ? 
ARG2_OR_DEF(n)
+                                                   : bgcol );
+                                               }
+                                       n+=(EXIST_ARG2(n) ? 2 : 1);
+                                       break;
+                               }
+                               if (ARG(n+1)==2) {
+                                       n=(edp->nargs-n > 5 ? n+4 :
+                                           edp->nargs);
+                                       break;
+                               }
+                               n++;
+                               break;
                        case 49:
                                /* reset bg color */
                                bgcol = WSCOL_BLACK;
                                if (fgcol == WSCOL_WHITE)
                                        flags &= ~WSATTR_WSCOLORS;
+                               break;
+                       case 90: case 91: case 92: case 93:
+                       case 94: case 95: case 96: case 97:
+                               /* bright foreground colour */
+                               flags |= WSATTR_WSCOLORS;
+                               fgcol = ARG(n) - 82;
+                               break;
+                       case 100: case 101: case 102: case 103:
+                       case 104: case 105: case 106: case 107:
+                               /* bright background colour */
+                               flags |= WSATTR_WSCOLORS;
+                               bgcol = ARG(n) - 92;
                                break;
                        default:
 #ifdef VT100_PRINTUNKNOWN
--- 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   Fri Jan  6 20:09:43 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
@@ -114,6 +119,7 @@
 #define WSSCREEN_HILIT         4       /* can highlight (however) */
 #define WSSCREEN_BLINK         8       /* can blink */
 #define WSSCREEN_UNDERLINE     16      /* can underline */
+#define WSSCREEN_256COL                32      /* supports 256 colours */
 };
 
 /*
--- 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 Fri Jan  6 20:57:48 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 */
 };
@@ -454,6 +454,10 @@
                    WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
        }
 
+       if (ri->ri_depth == 32) {
+               ri->ri_caps |= WSSCREEN_256COL ;
+       }
+
        switch (ri->ri_depth) {
 #if NRASOPS1 > 0
        case 1:
@@ -564,12 +568,24 @@
                fg = bg;
                bg = swap;
        }
-
-       if ((flg & WSATTR_HILIT) != 0)
+       /* Bold is only supported for 'normal' colours, I.E. 0 - 7 */
+       if (((flg & WSATTR_HILIT) != 0) && fg<8)
                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;
 
@@ -882,6 +898,21 @@
                ri->ri_devcmap[i] = c;
 #endif
        }
+       /* Re-define colours 16-255 if we are running in 32bpp */
+       #define EBCOL_RED(x) (48*((x-16)%6))
+       #define EBCOL_GREEN(x) ((48*(((x-16)/6)%6)) << 8)
+       #define EBCOL_BLUE(x) ((48*(((x-16)/36)%6)) << 16)
+       #define EBCOL(x) EBCOL_RED(x) | EBCOL_GREEN(x) | EBCOL_BLUE(x)
+       #define EBGREY(x) (int)(1+((i-232)*11))
+       if (ri->ri_depth == 32) {
+               for (i=16 ; i<=231; i++) {
+                       ri->ri_devcmap[i] = EBCOL(i);
+               }
+               for (i=232 ; i<256; i++) {
+                       ri->ri_devcmap[i] = EBGREY(i) | EBGREY(i) << 8 |
+                           EBGREY(i) << 16;
+               }
+       }
 #endif
 }
 
@@ -891,8 +922,8 @@
 void
 rasops_unpack_attr(void *cookie, uint32_t attr, int *fg, int *bg, int 
*underline)
 {
-       *fg = ((u_int)attr >> 24) & 0xf;
-       *bg = ((u_int)attr >> 16) & 0xf;
+       *fg = ((u_int)attr >> 24) & 0xff;
+       *bg = ((u_int)attr >> 16) & 0xff;
        if (underline != NULL)
                *underline = (u_int)attr & 1;
 }
@@ -922,7 +953,7 @@
                return 0;
 #endif
 
-       clr = ri->ri_devcmap[(attr >> 16) & 0xf];
+       clr = ri->ri_devcmap[(attr >> 16) & 0xff];
 
        /*
         * XXX The wsdisplay_emulops interface seems a little deficient in
@@ -1076,7 +1107,7 @@
        num = num * ri->ri_xscale;
        rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
        height = ri->ri_font->fontheight;
-       clr = ri->ri_devcmap[(attr >> 16) & 0xf];
+       clr = ri->ri_devcmap[(attr >> 16) & 0xff];
 
        /* Don't bother using the full loop for <= 32 pels */
        if (num <= 32) {
@@ -1277,7 +1308,7 @@
 
        /* XXX this assumes 16-bit color depth */
        if ((attr & 1) != 0) {
-               int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
+               int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xff];
 
                while (height--) {
                        *(int16_t *)rp = c;
@@ -1805,8 +1836,8 @@
        attr = ri->ri_bs[off].attr;
 
        if ((ri->ri_flg & RI_CURSOR) == 0) {
-               fg = ((u_int)attr >> 24) & 0xf;
-               bg = ((u_int)attr >> 16) & 0xf;
+               fg = ((u_int)attr >> 24) & 0xff;
+               bg = ((u_int)attr >> 16) & 0xff;
                attr &= ~0x0ffff0000;
                attr |= (fg << 16) | (bg << 24);
        }
--- dev/rasops/rasops.h.dist    Mon May 25 06:55:49 2020
+++ dev/rasops/rasops.h Fri Jan  6 11:00:30 2023
@@ -106,7 +106,7 @@
        u_char  *ri_origbits;   /* where screen bits actually start */
        int     ri_xorigin;     /* where ri_bits begins (x) */
        int     ri_yorigin;     /* where ri_bits begins (y) */
-       int32_t ri_devcmap[16]; /* color -> framebuffer data */
+       int32_t ri_devcmap[256]; /* color -> framebuffer data */
 
        /* The emulops you need to use, and the screen caps for wscons */
        struct  wsdisplay_emulops ri_ops;
--- dev/rasops/rasops32.c.dist  Mon Jul 20 09:40:45 2020
+++ dev/rasops/rasops32.c       Fri Jan  6 20:11:59 2023
@@ -91,13 +91,46 @@
        width = ri->ri_font->fontwidth;
        step = ri->ri_stride >> 3;
 
-       b = ri->ri_devcmap[(attr >> 16) & 0xf];
-       f = ri->ri_devcmap[(attr >> 24) & 0xf];
+       b = ri->ri_devcmap[(attr >> 16) & 0xff];
+       f = ri->ri_devcmap[(attr >> 24) & 0xff];
+
+       /*
+        * 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 byte-swapped BGR formats with exactly 8 bits per channel,
+        * I.E. 0xXXRRGGBB, and 0xBBGGRRXX.
+        *
+        * The unused byte is always set to 0x00 for 32bpp in
+        * rasops_init_devcmap, so will be unaffected by the shift.
+        *
+        * XXX If we ever support 32-bit devices that are not 8 bits per channel
+        * then this code will need to change.
+        */
+
+       if ((attr & WSATTR_DIM)!=0) {
+               f=(f>>1) & 0x7F7F7F7F;
+               }
+
        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 +235,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;
 }

Reply via email to