# New escape sequences and two one-line bugfixes

--- dev/wscons/wsemul_vt100_subr.c.dist Mon May 25 06:55:49 2020
+++ dev/wscons/wsemul_vt100_subr.c      Sat Jan  7 12:39:58 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,76 @@
                        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;
+                       /*
+                        * Sequences starting CSI 38 escape to a larger
+                        * colourspace, typically either 256 colours or 24-bit.
+                        *
+                        * We support CSI 38;5;X;m to set colour X from a
+                        * palette of 256.
+                        */
+#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 +702,46 @@
                                flags |= WSATTR_WSCOLORS;
                                bgcol = ARG(n) - 40;
                                break;
+                       case 48: /* set 8-bit background colour */
+                               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/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/rasops/rasops.c.dist    Thu Jul 23 06:17:03 2020
+++ dev/rasops/rasops.c Sat Jan  7 13:55:14 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       Sat Jan  7 13:56:43 2023
@@ -93,11 +93,44 @@
 
        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 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,45 @@
                }
        }
 
+       /* 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