From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Mike Hamrick Newsgroups: gmane.emacs.devel Subject: [PATCH] TTY Support for ECMA-48 strike-through graphic rendition Date: Thu, 25 Jun 2020 14:44:11 -0700 Message-ID: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="64407"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: mu4e 1.0; emacs 25.3.1 To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Jun 25 23:44:52 2020 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1joZfw-000GeP-6B for ged-emacs-devel@m.gmane-mx.org; Thu, 25 Jun 2020 23:44:52 +0200 Original-Received: from localhost ([::1]:52416 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1joZfv-0007FA-7j for ged-emacs-devel@m.gmane-mx.org; Thu, 25 Jun 2020 17:44:51 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:55754) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1joZfM-0006ky-FW for emacs-devel@gnu.org; Thu, 25 Jun 2020 17:44:16 -0400 Original-Received: from eidolon.muppetlabs.com ([207.66.255.52]:46024) by eggs.gnu.org with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.90_1) (envelope-from ) id 1joZfJ-0005UX-Hd for emacs-devel@gnu.org; Thu, 25 Jun 2020 17:44:15 -0400 Original-Received: from mikeh by eidolon.muppetlabs.com with local (Exim 4.82) (envelope-from ) id 1joZfH-00077z-AH for emacs-devel@gnu.org; Thu, 25 Jun 2020 14:44:11 -0700 X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: mikeh@muppetlabs.com X-SA-Exim-Scanned: No (on eidolon.muppetlabs.com); SAEximRunCond expanded to false Received-SPF: pass client-ip=207.66.255.52; envelope-from=mikeh@muppetlabs.com; helo=eidolon.muppetlabs.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/06/25 17:44:11 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:252536 Archived-At: Hello, In 1984, the third edition of ECMA-48 "Control Functions for Coded Character Sets" was published. In section 8.3.117 under "Select Graphic Rendition" a new character attribute for "crossed-out" was added. As Thomas Dickey notes, many escape sequences in ECMA-48 were in fact created by a committee, and did not exist in hardware terminals of the time, but were rather a framework for proposed terminal implementations. Some 30 years on, many terminal programs such as xterm, gnome-terminal, termite, st, konsole, and others have implemented the ECMA-48 strike-through escape sequences, however there wasn't a terminfo(5) capability defined for the purpose until a few years ago. Here is my patch which adds Emacs TTY support for strike-through rendering, which I personally use in org-mode for done TODO items. In order for this to work for you, your terminfo database entry needs to have the "smxx" capability defined, which I believe more recent versions[0] of the xterm entry have. [0]: https://invisible-island.net/xterm/terminfo.html * term.c: Support strike-through in capable terminals. (no_color_bit): Replace unused NC_INVIS with NC_STRIKE_THROUGH. (turn_on_face): Output via TS_enter_strike_through_mode if available. (turn_off_face): Handle strike-through case. (tty_capable_p, init_tty): Support strike-through. * termchar.h (struct tty_display_info): Add field for strike-through. * xfaces.c (tty_supports_face_attributes_p, realize_tty_face): Handle strike-through case. * dispextern.h: Add TTY_CAP_STRIKE_THROUGH definition. (struct face): Add field tty_strike_through_p. --- src/dispextern.h | 2 ++ src/term.c | 34 ++++++++++++++++++++-------------- src/termchar.h | 1 + src/xfaces.c | 12 +++++++++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index e1d6eddc41..082a345441 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1744,6 +1744,7 @@ #define FONT_TOO_HIGH(ft) \ bool_bf tty_italic_p : 1; bool_bf tty_underline_p : 1; bool_bf tty_reverse_p : 1; + bool_bf tty_strike_through_p : 1; /* True means that colors of this face may not be freed because they have been copied bitwise from a base face (see @@ -3290,6 +3291,7 @@ #define TTY_CAP_UNDERLINE 0x02 #define TTY_CAP_BOLD 0x04 #define TTY_CAP_DIM 0x08 #define TTY_CAP_ITALIC 0x10 +#define TTY_CAP_STRIKE_THROUGH 0x20 /*********************************************************************** diff --git a/src/term.c b/src/term.c index 5cbb092ad1..bf5e339d2f 100644 --- a/src/term.c +++ b/src/term.c @@ -105,14 +105,14 @@ #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } whil enum no_color_bit { - NC_STANDOUT = 1 << 0, - NC_UNDERLINE = 1 << 1, - NC_REVERSE = 1 << 2, - NC_ITALIC = 1 << 3, - NC_DIM = 1 << 4, - NC_BOLD = 1 << 5, - NC_INVIS = 1 << 6, - NC_PROTECT = 1 << 7 + NC_STANDOUT = 1 << 0, + NC_UNDERLINE = 1 << 1, + NC_REVERSE = 1 << 2, + NC_ITALIC = 1 << 3, + NC_DIM = 1 << 4, + NC_BOLD = 1 << 5, + NC_STRIKE_THROUGH = 1 << 6, + NC_PROTECT = 1 << 7 }; /* internal state */ @@ -1931,6 +1931,9 @@ turn_on_face (struct frame *f, int face_id) if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE)) OUTPUT1_IF (tty, tty->TS_enter_underline_mode); + if (face->tty_strike_through_p && MAY_USE_WITH_COLORS_P (tty, NC_STRIKE_THROUGH)) + OUTPUT1_IF (tty, tty->TS_enter_strike_through_mode); + if (tty->TN_max_colors > 0) { const char *ts; @@ -1971,7 +1974,8 @@ turn_off_face (struct frame *f, int face_id) if (face->tty_bold_p || face->tty_italic_p || face->tty_reverse_p - || face->tty_underline_p) + || face->tty_underline_p + || face->tty_strike_through_p) { OUTPUT1_IF (tty, tty->TS_exit_attribute_mode); if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0) @@ -2006,11 +2010,12 @@ #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \ if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \ return 0; - TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE); - TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE); - TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD); - TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM); - TTY_CAPABLE_P_TRY (tty, TTY_CAP_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_STRIKE_THROUGH, tty->TS_enter_strike_through_mode, NC_STRIKE_THROUGH); /* We can do it! */ return 1; @@ -4124,6 +4129,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) tty->TS_enter_alt_charset_mode = tgetstr ("as", address); tty->TS_exit_alt_charset_mode = tgetstr ("ae", address); tty->TS_exit_attribute_mode = tgetstr ("me", address); + tty->TS_enter_strike_through_mode = tgetstr ("smxx", address); MultiUp (tty) = tgetstr ("UP", address); MultiDown (tty) = tgetstr ("DO", address); diff --git a/src/termchar.h b/src/termchar.h index c96b81913b..a8b3051767 100644 --- a/src/termchar.h +++ b/src/termchar.h @@ -136,6 +136,7 @@ #define EMACS_TERMCHAR_H const char *TS_enter_reverse_mode; /* "mr" -- enter reverse video mode. */ const char *TS_exit_underline_mode; /* "us" -- start underlining. */ const char *TS_enter_underline_mode; /* "ue" -- end underlining. */ + const char *TS_enter_strike_through_mode; /* "smxx" -- turn on strike-through mode. */ /* "as"/"ae" -- start/end alternate character set. Not really supported, yet. */ diff --git a/src/xfaces.c b/src/xfaces.c index c4a4e1c94f..dc6ea5eacf 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -5207,7 +5207,6 @@ tty_supports_face_attributes_p (struct frame *f, || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX]) || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]) || !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) - || !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX]) || !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])) return false; @@ -5272,6 +5271,15 @@ tty_supports_face_attributes_p (struct frame *f, test_caps |= TTY_CAP_INVERSE; } + /* strike through */ + val = attrs[LFACE_STRIKE_THROUGH_INDEX]; + if (!UNSPECIFIEDP (val)) + { + if (face_attr_equal_p (val, def_attrs[LFACE_STRIKE_THROUGH_INDEX])) + return false; /* same as default */ + else + test_caps |= TTY_CAP_STRIKE_THROUGH; + } /* Color testing. */ @@ -6234,6 +6242,8 @@ realize_tty_face (struct face_cache *cache, face->tty_underline_p = true; if (!NILP (attrs[LFACE_INVERSE_INDEX])) face->tty_reverse_p = true; + if (!NILP (attrs[LFACE_STRIKE_THROUGH_INDEX])) + face->tty_strike_through_p = true; /* Map color names to color indices. */ map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted); -- 2.24.0