Continuing the move towards xterm becoming the default termtype for the
console...

This third version of the patchset adds the following features.  New features
since the last version are highlighted first:

NEW - Control sequences for dim text, invisible text, strike through, italic,
      and double underline attributes are now recognised and set flags in
      wscons.

NEW - Rendering of dim, invisible, struck, and double underlined text is now
      supported in rasops32.c, so users of 32bpp displays will see these text
      effects on the console.

NEW - The default number of scrollback screens has been increased from five to
      twenty.

* F1 - F4 now send different sequences.
* F13 - F24 now send different sequences, but see notes below about F13 - F16.
* With numlock OFF, keypad 5 is now 'begin' rather than unused.
* Home, End, keypad home, and keypad end now send different sequences.
* A new keysym has been added - KS_Backtab.
* Shift-TAB is now defined as KS_Backtab and sends ESC [ Z.
* Shift-F1 - Shift-F12 now send F13 - F24.
* Five new escape sequences added for cursor movement.

Running with this patch, all of the curses-based programs that I use on a
regular basis are working and usable with TERM=xterm.

The overall experience is much improved over TERM=vt220, as we get colour.

Even compared to pccon, we gain the ability to use colour together with
underline, show and hide the cursor, and use backtab.  We also gain the
practicality of relying on a very widely and well supported terminal
definition, (xterm), which could much more reasonably become the default than
could pccon.

Additionally, a small side benefit of changing the function key sequences from
those expected by pccon to those expected by xterm is that any programs or
scripts which ignore terminfo and are hard coded to work with xterm will now
work on the console as well.

--- 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 09:25:38 2023
@@ -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));
                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,
 };
 
 #if !defined(WSKBD_NO_INTL_LAYOUTS)
--- 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;
 }

Reply via email to