From c4cb7ed8e542dec8c92558d32975f369bd7d5872 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 19 Nov 2017 18:29:38 +0100 Subject: [PATCH] Beginnings of terminfo support. --with-terminfo must be added for configure and --terminfo to command line. terminfo is only used for output and not all sequences are changed. --- Makefile.config.in | 1 + configure.in | 4 + src/config/cmdline.c | 5 + src/main/version.c | 3 + src/terminal/Makefile | 1 + src/terminal/screen.c | 213 ++++++++++++++++++++++++++++++---------- src/terminal/terminal.c | 6 ++ 7 files changed, 179 insertions(+), 54 deletions(-) diff --git a/Makefile.config.in b/Makefile.config.in index dae94a96..30dea985 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -170,6 +170,7 @@ CONFIG_SMB = @CONFIG_SMB@ CONFIG_SPIDERMONKEY = @CONFIG_SPIDERMONKEY@ CONFIG_SSL = @CONFIG_SSL@ CONFIG_SYSMOUSE = @CONFIG_SYSMOUSE@ +CONFIG_TERMINFO = @CONFIG_TERMINFO@ CONFIG_TRUE_COLOR = @CONFIG_TRUE_COLOR@ CONFIG_URI_REWRITE = @CONFIG_URI_REWRITE@ CONFIG_UTF8 = @CONFIG_UTF8@ diff --git a/configure.in b/configure.in index a0e676e7..b08a2780 100644 --- a/configure.in +++ b/configure.in @@ -477,6 +477,10 @@ AC_DEFUN([EL_CONFIG_OPTIONAL_LIBRARY], EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GPM, gpm, gpm.h, gpm, Gpm_Open, [ --without-gpm disable gpm (mouse) support]) + +EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_TERMINFO, terminfo, term.h, ncurses, setupterm, + [ --with-terminfo enable terminfo support]) + # ELinks calls deflateInit2 with windowBits = MAX_WBITS | 32, to # enable automatic decoding of both zlib and gzip headers. This # feature was added in zlib 1.2.0.2; earlier versions return an error. diff --git a/src/config/cmdline.c b/src/config/cmdline.c index 0a5e91f3..dae037d1 100644 --- a/src/config/cmdline.c +++ b/src/config/cmdline.c @@ -932,6 +932,11 @@ union option_info cmdline_options_info[] = { INIT_OPT_COMMAND("", NULL, "stdin", OPT_HIDDEN, redir_cmd, NULL), + INIT_OPT_BOOL("", N_("Whether to use terminfo"), + "terminfo", 0, 0, + N_("When enabled, terminfo ncurses functions will be used " + "instead of hardcoded sequences.")), + INIT_OPT_BOOL("", N_("Touch files in ~/.elinks when running with -no-connect/-session-ring"), "touch-files", 0, 0, N_("When enabled, runtime state files (bookmarks, history, " diff --git a/src/main/version.c b/src/main/version.c index 214c1c75..84953f57 100644 --- a/src/main/version.c +++ b/src/main/version.c @@ -157,6 +157,9 @@ get_dyn_full_version(struct terminal *term, int more) #endif #ifdef CONFIG_LIBEVENT comma, (event_enabled ? _("libevent", term) : _("libevent (disabled)", term)), +#endif +#ifdef CONFIG_TERMINFO + comma, (get_cmd_opt_bool("terminfo") ? _("terminfo", term) : _("terminfo (disabled)", term)), #endif comma, (unsigned char *) NULL diff --git a/src/terminal/Makefile b/src/terminal/Makefile index 4d7bb458..a833776a 100644 --- a/src/terminal/Makefile +++ b/src/terminal/Makefile @@ -2,6 +2,7 @@ top_builddir=../.. include $(top_builddir)/Makefile.config OBJS-$(CONFIG_MOUSE) += mouse.o +OBJS-$(CONFIG_TERMINFO) += terminfo.o OBJS = \ color.o \ diff --git a/src/terminal/screen.c b/src/terminal/screen.c index 6ec2611e..fd74724e 100644 --- a/src/terminal/screen.c +++ b/src/terminal/screen.c @@ -21,6 +21,9 @@ #include "terminal/kbd.h" #include "terminal/screen.h" #include "terminal/terminal.h" +#ifdef CONFIG_TERMINFO +#include "terminal/terminfo.h" +#endif #include "util/conv.h" #include "util/error.h" #include "util/memory.h" @@ -246,6 +249,11 @@ struct screen_driver_opt { /* Whether the terminal supports combining characters. */ unsigned int combine:1; #endif /* CONFIG_COMBINE */ + +#ifdef CONFIG_TERMINFO + /* Whether use terminfo. */ + unsigned int terminfo:1; +#endif }; /** Used in @c add_char*() and @c redraw_screen() to reduce the logic. @@ -285,6 +293,9 @@ static const struct screen_driver_opt dumb_screen_driver_opt = { #ifdef CONFIG_COMBINE /* combine */ 0, #endif /* CONFIG_COMBINE */ +#ifdef CONFIG_TERMINFO + /* terminfo */ 0, +#endif }; /** Default options for ::TERM_VT100. */ @@ -305,6 +316,9 @@ static const struct screen_driver_opt vt100_screen_driver_opt = { #ifdef CONFIG_COMBINE /* combine */ 0, #endif /* CONFIG_COMBINE */ +#ifdef CONFIG_TERMINFO + /* terminfo */ 0, +#endif }; /** Default options for ::TERM_LINUX. */ @@ -325,6 +339,9 @@ static const struct screen_driver_opt linux_screen_driver_opt = { #ifdef CONFIG_COMBINE /* combine */ 0, #endif /* CONFIG_COMBINE */ +#ifdef CONFIG_TERMINFO + /* terminfo */ 0, +#endif }; /** Default options for ::TERM_KOI8. */ @@ -345,6 +362,9 @@ static const struct screen_driver_opt koi8_screen_driver_opt = { #ifdef CONFIG_COMBINE /* combine */ 0, #endif /* CONFIG_COMBINE */ +#ifdef CONFIG_TERMINFO + /* terminfo */ 0, +#endif }; /** Default options for ::TERM_FREEBSD. */ @@ -365,6 +385,9 @@ static const struct screen_driver_opt freebsd_screen_driver_opt = { #ifdef CONFIG_COMBINE /* combine */ 0, #endif /* CONFIG_COMBINE */ +#ifdef CONFIG_TERMINFO + /* terminfo */ 0, +#endif }; /** Default options for ::TERM_FBTERM. */ @@ -385,6 +408,9 @@ static const struct screen_driver_opt fbterm_screen_driver_opt = { #ifdef CONFIG_COMBINE /* combine */ 0, #endif /* CONFIG_COMBINE */ +#ifdef CONFIG_TERMINFO + /* terminfo */ 0, +#endif }; /** Default options for all the different types of terminals. @@ -501,7 +527,10 @@ set_screen_driver_opt(struct screen_driver *driver, struct option *term_spec) } else if (driver->type == TERM_VT100) { driver->opt.frame = frame_vt100; } - } /* !utf8_io */ + } /* !utf8_io */ +#ifdef CONFIG_TERMINFO + driver->opt.terminfo = get_cmd_opt_bool("terminfo"); +#endif } static int @@ -806,7 +835,14 @@ add_char16(struct string *screen, struct screen_driver *driver, italic != state->italic && driver->opt.italic ) { state->italic = italic; - add_term_string(screen, driver->opt.italic[!!italic]); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_italics(italic)); + } else +#endif + { + add_term_string(screen, driver->opt.italic[!!italic]); + } } if ( @@ -816,7 +852,14 @@ add_char16(struct string *screen, struct screen_driver *driver, underline != state->underline && driver->opt.underline ) { state->underline = underline; - add_term_string(screen, driver->opt.underline[!!underline]); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_underline(underline)); + } else +#endif + { + add_term_string(screen, driver->opt.underline[!!underline]); + } } if ( @@ -827,7 +870,14 @@ add_char16(struct string *screen, struct screen_driver *driver, ) { state->bold = bold; if (bold) { - add_bytes_to_string(screen, "\033[1m", 4); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_bold(bold)); + } else +#endif + { + add_bytes_to_string(screen, "\033[1m", 4); + } } else { /* Force repainting of the other attributes. */ state->color[0] = ch->c.color[0] + 1; @@ -842,49 +892,65 @@ add_char16(struct string *screen, struct screen_driver *driver, ) { copy_color_16(state->color, ch->c.color); - add_bytes_to_string(screen, "\033[0", 3); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_bold(bold)); + add_to_string(screen, terminfo_set_foreground(TERM_COLOR_FOREGROUND_16(ch->c.color))); + add_to_string(screen, terminfo_set_background(TERM_COLOR_BACKGROUND_16(ch->c.color))); - /* @set_screen_driver_opt has set @driver->opt.color_mode - * according to terminal-type-specific options. - * The caller of @add_char16 has already partially - * checked it, but there are still these possibilities: - * - COLOR_MODE_MONO. Then don't show colors, but - * perhaps use the standout attribute. - * - COLOR_MODE_16. Use 16 colors. - * - An unsupported color mode. Use 16 colors. */ - if (driver->opt.color_mode != COLOR_MODE_MONO) { - unsigned char code[6] = ";30;40"; - unsigned char bgcolor = TERM_COLOR_BACKGROUND_16(ch->c.color); + if (italic) + add_to_string(screen, terminfo_set_italics(italic)); - code[2] += TERM_COLOR_FOREGROUND_16(ch->c.color); + if (underline) + add_to_string(screen, terminfo_set_underline(underline)); - if (!driver->opt.transparent || bgcolor != 0) { - code[5] += bgcolor; - add_bytes_to_string(screen, code, 6); - } else { - add_bytes_to_string(screen, code, 3); + } else +#endif + { + add_bytes_to_string(screen, "\033[0", 3); + + /* @set_screen_driver_opt has set @driver->opt.color_mode + * according to terminal-type-specific options. + * The caller of @add_char16 has already partially + * checked it, but there are still these possibilities: + * - COLOR_MODE_MONO. Then don't show colors, but + * perhaps use the standout attribute. + * - COLOR_MODE_16. Use 16 colors. + * - An unsupported color mode. Use 16 colors. */ + if (driver->opt.color_mode != COLOR_MODE_MONO) { + unsigned char code[6] = ";30;40"; + unsigned char bgcolor = TERM_COLOR_BACKGROUND_16(ch->c.color); + + code[2] += TERM_COLOR_FOREGROUND_16(ch->c.color); + + if (!driver->opt.transparent || bgcolor != 0) { + code[5] += bgcolor; + add_bytes_to_string(screen, code, 6); + } else { + add_bytes_to_string(screen, code, 3); + } + + } else if (ch->attr & SCREEN_ATTR_STANDOUT) { + /* Flip the fore- and background colors for highlighing + * purposes. */ + add_bytes_to_string(screen, ";7", 2); } - } else if (ch->attr & SCREEN_ATTR_STANDOUT) { - /* Flip the fore- and background colors for highlighing - * purposes. */ - add_bytes_to_string(screen, ";7", 2); - } + if (italic && driver->opt.italic) { + add_bytes_to_string(screen, ";3", 2); + } - if (italic && driver->opt.italic) { - add_bytes_to_string(screen, ";3", 2); - } + if (underline && driver->opt.underline) { + add_bytes_to_string(screen, ";4", 2); + } - if (underline && driver->opt.underline) { - add_bytes_to_string(screen, ";4", 2); - } + /* Check if the char should be rendered bold. */ + if (bold) { + add_bytes_to_string(screen, ";1", 2); + } - /* Check if the char should be rendered bold. */ - if (bold) { - add_bytes_to_string(screen, ";1", 2); + add_bytes_to_string(screen, "m", 1); } - - add_bytes_to_string(screen, "m", 1); } add_char_data(screen, driver, ch->data, border); @@ -961,17 +1027,38 @@ add_char256(struct string *screen, struct screen_driver *driver, if ((attr_delta & SCREEN_ATTR_ITALIC) && driver->opt.italic) { state->italic = !!(ch->attr & SCREEN_ATTR_ITALIC); - add_term_string(screen, driver->opt.italic[state->italic]); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_italics(state->italic)); + } else +#endif + { + add_term_string(screen, driver->opt.italic[state->italic]); + } } if ((attr_delta & SCREEN_ATTR_UNDERLINE) && driver->opt.underline) { state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); - add_term_string(screen, driver->opt.underline[state->underline]); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_underline(state->underline)); + } else +#endif + { + add_term_string(screen, driver->opt.underline[state->underline]); + } } if (attr_delta & SCREEN_ATTR_BOLD) { if (ch->attr & SCREEN_ATTR_BOLD) { - add_bytes_to_string(screen, "\033[1m", 4); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_bold(1)); + } else +#endif + { + add_bytes_to_string(screen, "\033[1m", 4); + } } else { /* Force repainting of the other attributes. */ state->color[0] = ch->c.color[0] + 1; @@ -988,23 +1075,41 @@ add_char256(struct string *screen, struct screen_driver *driver, !compare_color_256(ch->c.color, state->color) ) { copy_color_256(state->color, ch->c.color); +#ifdef CONFIG_TERMINFO + if (driver->opt.terminfo) { + add_to_string(screen, terminfo_set_bold(ch->attr & SCREEN_ATTR_BOLD)); + add_to_string(screen, terminfo_set_foreground(ch->c.color[0])); + add_to_string(screen, terminfo_set_background(ch->c.color[1])); - add_foreground_color(screen, driver->opt.color256_seqs, ch); - if (!driver->opt.transparent || ch->c.color[1] != 0) { - add_background_color(screen, driver->opt.color256_seqs, ch); - } + if (ch->attr & SCREEN_ATTR_ITALIC && driver->opt.italic) { + state->italic = !!(ch->attr & SCREEN_ATTR_ITALIC); + add_to_string(screen, terminfo_set_italics(state->italic)); + } - if (ch->attr & SCREEN_ATTR_BOLD) - add_bytes_to_string(screen, "\033[1m", 4); + if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->opt.underline) { + state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); + add_to_string(screen, terminfo_set_underline(state->underline)); + } + } else +#endif + { + add_foreground_color(screen, driver->opt.color256_seqs, ch); + if (!driver->opt.transparent || ch->c.color[1] != 0) { + add_background_color(screen, driver->opt.color256_seqs, ch); + } - if (ch->attr & SCREEN_ATTR_ITALIC && driver->opt.italic) { - state->italic = !!(ch->attr & SCREEN_ATTR_ITALIC); - add_term_string(screen, driver->opt.italic[state->italic]); - } + if (ch->attr & SCREEN_ATTR_BOLD) + add_bytes_to_string(screen, "\033[1m", 4); - if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->opt.underline) { - state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); - add_term_string(screen, driver->opt.underline[state->underline]); + if (ch->attr & SCREEN_ATTR_ITALIC && driver->opt.italic) { + state->italic = !!(ch->attr & SCREEN_ATTR_ITALIC); + add_term_string(screen, driver->opt.italic[state->italic]); + } + + if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->opt.underline) { + state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); + add_term_string(screen, driver->opt.underline[state->underline]); + } } } diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 30f21a30..a333baeb 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -33,6 +33,9 @@ #include "terminal/kbd.h" #include "terminal/screen.h" #include "terminal/terminal.h" +#ifdef CONFIG_TERMINFO +#include "terminal/terminfo.h" +#endif #include "terminal/window.h" #include "util/error.h" #include "util/memory.h" @@ -101,6 +104,9 @@ init_term(int fdin, int fdout) return NULL; } +#ifdef CONFIG_TERMINFO + terminfo_setupterm(NULL, fdout); +#endif init_list(term->windows); term->fdin = fdin;