From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: =?ISO-8859-1?Q?R=FCdiger?= Sonderfeld Newsgroups: gmane.emacs.devel Subject: [RFC-2] Add tty True Color support. Date: Thu, 17 Oct 2013 00:39:23 +0200 Message-ID: <2026164.mh4ZqmuNeq@descartes> References: <83wqldngnk.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Trace: ger.gmane.org 1381963201 17027 80.91.229.3 (16 Oct 2013 22:40:01 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 16 Oct 2013 22:40:01 +0000 (UTC) Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Oct 17 00:40:06 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VWZl7-0003WY-In for ged-emacs-devel@m.gmane.org; Thu, 17 Oct 2013 00:40:05 +0200 Original-Received: from localhost ([::1]:49598 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VWZl7-0003gS-6g for ged-emacs-devel@m.gmane.org; Wed, 16 Oct 2013 18:40:05 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:38514) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VWZkz-0003g6-Gy for emacs-devel@gnu.org; Wed, 16 Oct 2013 18:40:02 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VWZku-00047b-27 for emacs-devel@gnu.org; Wed, 16 Oct 2013 18:39:57 -0400 Original-Received: from ptmx.org ([178.63.28.110]:39398) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VWZko-00046n-06; Wed, 16 Oct 2013 18:39:46 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by ptmx.org (Postfix) with ESMTP id A10F12AFA6; Thu, 17 Oct 2013 00:39:43 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at ptmx.org Original-Received: from ptmx.org ([127.0.0.1]) by localhost (ptmx.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ESyMgT4-V2Ke; Thu, 17 Oct 2013 00:39:29 +0200 (CEST) Original-Received: from descartes.localnet (chello080108246092.7.14.vie.surfer.at [80.108.246.92]) by ptmx.org (Postfix) with ESMTPSA id 70A0E2AF14; Thu, 17 Oct 2013 00:39:29 +0200 (CEST) User-Agent: KMail/4.10.5 (Linux/3.8.0-30-generic; KDE/4.10.5; x86_64; ; ) In-Reply-To: <83wqldngnk.fsf@gnu.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 178.63.28.110 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 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.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:164256 Archived-At: Hello, > I might be missing something, but it looks like you didn't make any > changes aimed at having display-color-cells report the correct number= > of colors for this type of terminal. If that is true, please add som= e > code to fix that, otherwise various parts in Emacs might behave > incorrectly; for starters, defface's that define colors based on how > many colors are available will use the wrong colors. I changed `tty-display-color-cells' to return the correct number. See = the updated patch below. Do you have any suggestion how to do the terminal detection? So far Th= omas Dickey seems to be reluctant to add support to terminfo. Maybe there c= ould be a lisp function to detect it, which could be easily adjusted by the = user. But then again `init_tty' can be called very early in the start up proc= ess. Regards, R=C3=BCdiger -- 8< --------------------------------------------------------- >8 -- Some terminals support True Color (24bit RGB) values. At leas KDE's Konsole, st, and iTerm2 support it. This patch makes True Color support available in Emacs. So far there is no reliable way to detect True Color support in terminals and the terminfo database lacks support. I started a discussion on the ncurses mailing list[1]. So far only Konsole is supported by detecting the KONSOLE_DBUS_SESSION environment variable. But this should be replaced by a more reliable method. [1] https://lists.gnu.org/archive/html/bug-ncurses/2013-10/msg00007.htm= l * src/term.c (turn_on_face): Support True Color. (default_set_rgb_foreground): New variable. (default_set_rgb_background): New variable. (tty_default_color_capabilities): Save/restore set_rgb_*ground variables. (tty_setup_colors): Add support for True Color (16777216). (init_tty): Detect terminal True Color support. (Ftty_display_color_cells): Return correct number for True Color terms. * src/termchar.h (struct tty_display_info): Add TS_set_rgb_foreground, TS_set_rgb_background. * src/xfaces.c (tty_lookup_color): Encode colors as True Color if supported on frame. Signed-off-by: R=C3=BCdiger Sonderfeld --- src/term.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++= +------- src/termchar.h | 4 ++ src/xfaces.c | 103 ++++++++++++++++++++++++++++++-------------------= 3 files changed, 171 insertions(+), 54 deletions(-) diff --git a/src/term.c b/src/term.c index ee81c59..f9a398f 100644 --- a/src/term.c +++ b/src/term.c @@ -1960,21 +1960,57 @@ struct fkey_table { const char *ts; char *p; =20 - ts =3D tty->standout_mode ? tty->TS_set_background : tty->TS_set= _foreground; - if (fg >=3D 0 && ts) -=09{ - p =3D tparam (ts, NULL, 0, fg, 0, 0, 0); -=09 OUTPUT (tty, p); -=09 xfree (p); -=09} + if (fg > 0 && fg & (1 << 24)) /* RGB color */ + { + ts =3D tty->standout_mode ? tty->TS_set_rgb_background + : tty->TS_set_rgb_foreground; + if (ts) + { + const unsigned char r =3D (fg & 0xFF0000) >> 16, + g =3D (fg & 0x00FF00) >> 8, + b =3D (fg & 0x0000FF); + p =3D tparam (ts, NULL, 0, r, g, b, 0); + OUTPUT (tty, p); + xfree (p); + } + } + else + { + ts =3D tty->standout_mode ? tty->TS_set_background + : tty->TS_set_foreground; + if (fg >=3D 0 && ts) + { + p =3D tparam (ts, NULL, 0, fg, 0, 0, 0); + OUTPUT (tty, p); + xfree (p); + } + } =20 - ts =3D tty->standout_mode ? tty->TS_set_foreground : tty->TS_set= _background; - if (bg >=3D 0 && ts) -=09{ - p =3D tparam (ts, NULL, 0, bg, 0, 0, 0); -=09 OUTPUT (tty, p); -=09 xfree (p); -=09} + if (bg > 0 && bg & (1 << 24)) /* RGB color */ + { + ts =3D tty->standout_mode ? tty->TS_set_rgb_foreground + : tty->TS_set_rgb_background; + if (ts) + { + const unsigned char r =3D (bg & 0xFF0000) >> 16, + g =3D (bg & 0x00FF00) >> 8, + b =3D (bg & 0x0000FF); + p =3D tparam (ts, NULL, 0, r, g, b, 0); + OUTPUT (tty, p); + xfree (p); + } + } + else + { + ts =3D tty->standout_mode ? tty->TS_set_foreground + : tty->TS_set_background; + if (bg >=3D 0 && ts) + { + p =3D tparam (ts, NULL, 0, bg, 0, 0, 0); + OUTPUT (tty, p); + xfree (p); + } + } } } =20 @@ -2075,6 +2111,8 @@ struct fkey_table { struct terminal *t =3D get_tty_terminal (terminal, 0); if (!t) return make_number (0); + else if (t->display_info.tty->TS_set_rgb_foreground) + return make_number (16777216); /* 24 bit True Color */ else return make_number (t->display_info.tty->TN_max_colors); } @@ -2090,6 +2128,8 @@ struct fkey_table { static char *default_orig_pair; static char *default_set_foreground; static char *default_set_background; +static char *default_set_rgb_foreground; +static char *default_set_rgb_background; =20 /* Save or restore the default color-related capabilities of this terminal. */ @@ -2110,6 +2150,16 @@ struct fkey_table { default_set_background =3D tty->TS_set_background ? xstrdup (tty= ->TS_set_background) =09=09=09 : NULL; =20 + xfree (default_set_rgb_foreground); + default_set_rgb_foreground =3D tty->TS_set_rgb_foreground + ? xstrdup (tty->TS_set_rgb_foregrou= nd) + : NULL; + + xfree (default_set_rgb_background); + default_set_rgb_foreground =3D tty->TS_set_rgb_background + ? xstrdup (tty->TS_set_rgb_backgrou= nd) + : NULL; + default_max_colors =3D tty->TN_max_colors; default_max_pairs =3D tty->TN_max_pairs; default_no_color_video =3D tty->TN_no_color_video; @@ -2119,6 +2169,8 @@ struct fkey_table { tty->TS_orig_pair =3D default_orig_pair; tty->TS_set_foreground =3D default_set_foreground; tty->TS_set_background =3D default_set_background; + tty->TS_set_rgb_foreground =3D default_set_rgb_foreground; + tty->TS_set_rgb_background =3D default_set_rgb_background; tty->TN_max_colors =3D default_max_colors; tty->TN_max_pairs =3D default_max_pairs; tty->TN_no_color_video =3D default_no_color_video; @@ -2143,6 +2195,7 @@ struct fkey_table { =09tty->TN_max_pairs =3D 0; =09tty->TN_no_color_video =3D 0; =09tty->TS_set_foreground =3D tty->TS_set_background =3D tty->TS_orig_= pair =3D NULL; + tty->TS_set_rgb_foreground =3D tty->TS_set_rgb_background =3D = NULL; =09break; case 0:=09 /* default colors, if any */ default: @@ -2157,10 +2210,29 @@ struct fkey_table { =09tty->TS_set_foreground =3D "\033[3%dm"; =09tty->TS_set_background =3D "\033[4%dm"; #endif + tty->TS_set_rgb_foreground =3D NULL; + tty->TS_set_rgb_background =3D NULL; =09tty->TN_max_colors =3D 8; =09tty->TN_max_pairs =3D 64; =09tty->TN_no_color_video =3D 0; =09break; + case 16777216: /* RGB colors */ + tty->TS_orig_pair =3D "\033[0m"; +#ifdef TERMINFO +=09tty->TS_set_foreground =3D "\033[3%p1%dm"; +=09tty->TS_set_background =3D "\033[4%p1%dm"; + tty->TS_set_rgb_foreground =3D "\E[38;2;%p1%d;%p2%d;%p3%dm"; + tty->TS_set_rgb_background =3D "\E[48;2;%p1%d;%p2%d;%p3%dm"; +#else +=09tty->TS_set_foreground =3D "\033[3%dm"; +=09tty->TS_set_background =3D "\033[4%dm"; + tty->TS_set_rgb_foreground =3D "\E[38;2;%d;%d;%dm"; + tty->TS_set_rgb_background =3D "\E[48;2;%d;%d;%dm"; +#endif + tty->TN_max_colors =3D 16777216; + /*tty->TN_max_pairs =3D 64; TODO */ +=09tty->TN_no_color_video =3D 0; + break; } } =20 @@ -4227,6 +4299,24 @@ struct terminal * tty->TN_no_color_video =3D tgetnum ("NC"); if (tty->TN_no_color_video =3D=3D -1) tty->TN_no_color_video =3D 0; + + /* TODO Reliable way to detect: Konsole, iTerm2, st */ + if (getenv ("KONSOLE_DBUS_SESSION")) + { + /* TODO This should be extracted from terminfo/termcap. */ +#ifdef TERMINFO + tty->TS_set_rgb_foreground =3D "\E[38;2;%p1%d;%p2%d;%p3%dm";= + tty->TS_set_rgb_background =3D "\E[48;2;%p1%d;%p2%d;%p3%dm";= +#else + tty->TS_set_rgb_foreground =3D "\E[38;2;%d;%d;%dm"; + tty->TS_set_rgb_background =3D "\E[48;2;%d;%d;%dm"; +#endif + } + else + { + tty->TS_set_rgb_foreground =3D NULL; + tty->TS_set_rgb_background =3D NULL; + } } =20 tty_default_color_capabilities (tty, 1); diff --git a/src/termchar.h b/src/termchar.h index feb89e0..6ef0c16 100644 --- a/src/termchar.h +++ b/src/termchar.h @@ -156,6 +156,10 @@ struct tty_display_info const char *TS_set_foreground; const char *TS_set_background; =20 + /* Support for 24bit RGB color terminals. */ + const char *TS_set_rgb_foreground; + const char *TS_set_rgb_background; + int TF_hazeltine; /* termcap hz flag. */ int TF_insmode_motion; /* termcap mi flag: can move while in = insert mode. */ int TF_standout_motion; /* termcap mi flag: can move while in = standout mode. */ diff --git a/src/xfaces.c b/src/xfaces.c index 828788b..3d53563 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -960,54 +960,77 @@ static struct face *realize_non_ascii_face (struc= t frame *, Lisp_Object, if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc))) return 0; =20 - XSETFRAME (frame, f); - - color_desc =3D call2 (Qtty_color_desc, color, frame); - if (CONSP (color_desc) && CONSP (XCDR (color_desc))) + if (f->output_method =3D=3D output_termcap + && f->output_data.tty->display_info->TS_set_rgb_foreground + && !NILP (Ffboundp (Qtty_color_standard_values))) { - Lisp_Object rgb; - - if (! INTEGERP (XCAR (XCDR (color_desc)))) -=09return 0; + /* Terminal supports 3 byte RGB colors. */ + color_desc =3D call1 (Qtty_color_standard_values, color); + if (! parse_rgb_list (color_desc, tty_color)) + return 0; =20 - tty_color->pixel =3D XINT (XCAR (XCDR (color_desc))); + /* Map XColor to 3 byte values. */ + tty_color->pixel =3D 1 << 24 /* Set bit 24 to mark RGB values. *= / + | (tty_color->red / 257) << 16 + | (tty_color->green / 257) << 8 + | (tty_color->blue / 257); =20 - rgb =3D XCDR (XCDR (color_desc)); - if (! parse_rgb_list (rgb, tty_color)) -=09return 0; - - /* Should we fill in STD_COLOR too? */ if (std_color) -=09{ -=09 /* Default STD_COLOR to the same as TTY_COLOR. */ -=09 *std_color =3D *tty_color; - -=09 /* Do a quick check to see if the returned descriptor is -=09 actually _exactly_ equal to COLOR, otherwise we have to -=09 lookup STD_COLOR separately. If it's impossible to lookup -=09 a standard color, we just give up and use TTY_COLOR. */ -=09 if ((!STRINGP (XCAR (color_desc)) -=09 || NILP (Fstring_equal (color, XCAR (color_desc)))) -=09 && !NILP (Ffboundp (Qtty_color_standard_values))) -=09 { -=09 /* Look up STD_COLOR separately. */ -=09 rgb =3D call1 (Qtty_color_standard_values, color); -=09 if (! parse_rgb_list (rgb, std_color)) -=09=09return 0; -=09 } -=09} + *std_color =3D *tty_color; =20 return 1; } - else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist")))) - /* We were called early during startup, and the colors are not - yet set up in tty-defined-color-alist. Don't return a failure - indication, since this produces the annoying "Unable to - load color" messages in the *Messages* buffer. */ - return 1; else - /* tty-color-desc seems to have returned a bad value. */ - return 0; + { + XSETFRAME (frame, f); + + color_desc =3D call2 (Qtty_color_desc, color, frame); + if (CONSP (color_desc) && CONSP (XCDR (color_desc))) + { + Lisp_Object rgb; + + if (! INTEGERP (XCAR (XCDR (color_desc)))) + return 0; + + tty_color->pixel =3D XINT (XCAR (XCDR (color_desc))); + + rgb =3D XCDR (XCDR (color_desc)); + if (! parse_rgb_list (rgb, tty_color)) + return 0; + + /* Should we fill in STD_COLOR too? */ + if (std_color) + { + /* Default STD_COLOR to the same as TTY_COLOR. */ + *std_color =3D *tty_color; + + /* Do a quick check to see if the returned descriptor is= + actually _exactly_ equal to COLOR, otherwise we have = to + lookup STD_COLOR separately. If it's impossible to l= ookup + a standard color, we just give up and use TTY_COLOR. = */ + if ((!STRINGP (XCAR (color_desc)) + || NILP (Fstring_equal (color, XCAR (color_desc))))= + && !NILP (Ffboundp (Qtty_color_standard_values))) + { + /* Look up STD_COLOR separately. */ + rgb =3D call1 (Qtty_color_standard_values, color); + if (! parse_rgb_list (rgb, std_color)) + return 0; + } + } + + return 1; + } + else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist")= ))) + /* We were called early during startup, and the colors are not= + yet set up in tty-defined-color-alist. Don't return a fail= ure + indication, since this produces the annoying "Unable to + load color" messages in the *Messages* buffer. */ + return 1; + else + /* tty-color-desc seems to have returned a bad value. */ + return 0; + } } =20 /* A version of defined_color for non-X frames. */ --=20 1.8.4