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.  The latter, however, shows
'^@^@' before the PS1 prompt upon starting a new session (`tmux new`),
behavior I don't see with a 'real' xterm.

I like the idea, thanks for your work on this diff.

Paul

On Wed, Jan 04, 2023 at 10:42:56AM -0300, Crystal Kolipe wrote:
| 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;
|  }
| 

-- 
>++++++++[<++++++++++>-]<+++++++.>+++[<------>-]<.>+++[<+
+++++++++++>-]<.>++[<------------>-]<+.--------------.[-]
                 http://www.weirdnet.nl/                 

Reply via email to