diff options
Diffstat (limited to 'src/fe-text/terminfo-core.c')
-rw-r--r-- | src/fe-text/terminfo-core.c | 189 |
1 files changed, 111 insertions, 78 deletions
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index d16987fe..9c9179a5 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -17,7 +17,6 @@ inline static int term_putchar(int c) char *tparm(); int tputs(); -#ifdef HAVE_TERMINFO int setupterm(); char *tigetstr(); int tigetnum(); @@ -25,15 +24,6 @@ int tigetflag(); #define term_getstr(x, buffer) tigetstr(x.ti_name) #define term_getnum(x) tigetnum(x.ti_name); #define term_getflag(x) tigetflag(x.ti_name); -#else -int tgetent(); -char *tgetstr(); -int tgetnum(); -int tgetflag(); -#define term_getstr(x, buffer) tgetstr(x.tc_name, &buffer) -#define term_getnum(x) tgetnum(x.tc_name) -#define term_getflag(x) tgetflag(x.tc_name) -#endif #define CAP_TYPE_FLAG 0 #define CAP_TYPE_INT 1 @@ -50,62 +40,66 @@ TERM_REC *current_term; /* Define only what we might need */ static TERMINFO_REC tcaps[] = { - /* Terminal size */ - { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) }, - { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) }, - - /* Cursor movement */ - { "smcup", "ti", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smcup) }, - { "rmcup", "te", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmcup) }, - { "cup", "cm", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cup) }, - { "hpa", "ch", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_hpa) }, - { "vpa", "vh", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_vpa) }, - { "cub1", "le", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cub1) }, - { "cuf1", "nd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cuf1) }, - { "civis", "vi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_civis) }, - { "cnorm", "ve", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cnorm) }, + /* Terminal size */ + { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) }, + { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) }, - /* Scrolling */ - { "csr", "cs", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_csr) }, - { "wind", "wi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_wind) }, - { "ri", "sr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ri) }, - { "rin", "SR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rin) }, - { "ind", "sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ind) }, - { "indn", "SF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_indn) }, - { "il", "AL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il) }, - { "il1", "al", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il1) }, - { "dl", "DL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl) }, - { "dl1", "dl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl1) }, + /* Cursor movement */ + { "smcup", "ti", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smcup) }, + { "rmcup", "te", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmcup) }, + { "cup", "cm", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cup) }, + { "hpa", "ch", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_hpa) }, + { "vpa", "vh", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_vpa) }, + { "cub1", "le", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cub1) }, + { "cuf1", "nd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cuf1) }, + { "civis", "vi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_civis) }, + { "cnorm", "ve", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cnorm) }, + + /* Scrolling */ + { "csr", "cs", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_csr) }, + { "wind", "wi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_wind) }, + { "ri", "sr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ri) }, + { "rin", "SR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rin) }, + { "ind", "sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ind) }, + { "indn", "SF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_indn) }, + { "il", "AL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il) }, + { "il1", "al", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il1) }, + { "dl", "DL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl) }, + { "dl1", "dl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl1) }, /* Clearing screen */ - { "clear", "cl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_clear) }, - { "ed", "cd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ed) }, + { "clear", "cl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_clear) }, + { "ed", "cd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ed) }, - /* Clearing to end of line */ - { "el", "ce", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_el) }, + /* Clearing to end of line */ + { "el", "ce", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_el) }, - /* Repeating character */ - { "rep", "rp", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rep) }, + /* Repeating character */ + { "rep", "rp", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rep) }, /* Colors */ - { "colors", "Co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, TI_colors) }, - { "sgr0", "me", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sgr0) }, - { "smul", "us", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smul) }, - { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) }, - { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) }, - { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) }, - { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) }, - { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) }, - { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) }, - { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) }, - { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) }, - { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) }, - { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) }, - { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) }, - { "setb", "Sb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setb) }, - - /* Beep */ - { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) }, + { "colors", "Co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, TI_colors) }, + { "sgr0", "me", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sgr0) }, + { "smul", "us", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smul) }, + { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) }, + { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) }, + { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) }, + { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) }, + { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) }, + { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) }, + { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) }, + { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) }, + { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) }, + { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) }, + { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) }, + { "setb", "Sb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setb) }, + + /* Beep */ + { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) }, + + /* Keyboard-transmit mode */ + { "smkx", "ks", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smkx) }, + { "rmkx", "ke", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmkx) }, }; /* Move cursor (cursor_address / cup) */ @@ -391,15 +385,26 @@ static void _ignore_parm(TERM_REC *term, int param) { } +static void terminfo_set_appkey_mode(TERM_REC *term, int set) +{ + if (term->TI_smkx && term->TI_rmkx) + tput(tparm(set ? term->TI_smkx : term->TI_rmkx)); +} + +static void term_dec_set_bracketed_paste_mode(int enable) +{ + if (enable) + tputs("\e[?2004h", 0, term_putchar); + else + tputs("\e[?2004l", 0, term_putchar); +} + static void term_fill_capabilities(TERM_REC *term) { int i, ival; char *sval; void *ptr; -#ifndef HAVE_TERMINFO - char *tptr = term->buffer2; -#endif for (i = 0; i < sizeof(tcaps)/sizeof(tcaps[0]); i++) { ptr = G_STRUCT_MEMBER_P(term, tcaps[i].offset); @@ -492,12 +497,15 @@ void terminfo_setup_colors(TERM_REC *term, int force) } } -static void terminfo_input_init(TERM_REC *term) +static void terminfo_input_init0(TERM_REC *term) { tcgetattr(fileno(term->in), &term->old_tio); memcpy(&term->tio, &term->old_tio, sizeof(term->tio)); term->tio.c_lflag &= ~(ICANON | ECHO); /* CBREAK, no ECHO */ + /* Disable the ICRNL flag to disambiguate ^J and Enter, also disable the + * software flow control to leave ^Q and ^S ready to be bound */ + term->tio.c_iflag &= ~(ICRNL | IXON | IXOFF); term->tio.c_cc[VMIN] = 1; /* read() is satisfied after 1 char */ term->tio.c_cc[VTIME] = 0; /* No timer */ @@ -511,8 +519,11 @@ static void terminfo_input_init(TERM_REC *term) term->tio.c_cc[VSUSP] = _POSIX_VDISABLE; #endif - tcsetattr(fileno(term->in), TCSADRAIN, &term->tio); +} +static void terminfo_input_init(TERM_REC *term) +{ + tcsetattr(fileno(term->in), TCSADRAIN, &term->tio); } static void terminfo_input_deinit(TERM_REC *term) @@ -523,7 +534,14 @@ static void terminfo_input_deinit(TERM_REC *term) void terminfo_cont(TERM_REC *term) { if (term->TI_smcup) - tput(tparm(term->TI_smcup)); + tput(tparm(term->TI_smcup)); + + if (term->appkey_enabled) + terminfo_set_appkey_mode(term, TRUE); + + if (term->bracketed_paste_enabled) + term_dec_set_bracketed_paste_mode(TRUE); + terminfo_input_init(term); } @@ -534,10 +552,16 @@ void terminfo_stop(TERM_REC *term) /* move cursor to bottom of the screen */ terminfo_move(0, term->height-1); + if (term->bracketed_paste_enabled) + term_dec_set_bracketed_paste_mode(FALSE); + /* stop cup-mode */ if (term->TI_rmcup) tput(tparm(term->TI_rmcup)); + if (term->appkey_enabled) + terminfo_set_appkey_mode(term, FALSE); + /* reset input settings */ terminfo_input_deinit(term); fflush(term->out); @@ -546,9 +570,7 @@ void terminfo_stop(TERM_REC *term) static int term_setup(TERM_REC *term) { GString *str; -#ifdef HAVE_TERMINFO int err; -#endif char *term_env; term_env = getenv("TERM"); @@ -557,18 +579,10 @@ static int term_setup(TERM_REC *term) return 0; } -#ifdef HAVE_TERMINFO if (setupterm(term_env, 1, &err) != 0) { fprintf(stderr, "setupterm() failed for TERM=%s: %d\n", term_env, err); return 0; } -#else - if (tgetent(term->buffer1, term_env) < 1) - { - fprintf(stderr, "Termcap not found for TERM=%s\n", term_env); - return 0; - } -#endif term_fill_capabilities(term); @@ -646,11 +660,11 @@ static int term_setup(TERM_REC *term) str = g_string_new(NULL); if (term->TI_sgr0) g_string_append(str, term->TI_sgr0); - if (term->TI_rmul && (term->TI_sgr0 == NULL || strcmp(term->TI_rmul, term->TI_sgr0) != 0)) + if (term->TI_rmul && (term->TI_sgr0 == NULL || g_strcmp0(term->TI_rmul, term->TI_sgr0) != 0)) g_string_append(str, term->TI_rmul); - if (term->TI_rmso && (term->TI_sgr0 == NULL || strcmp(term->TI_rmso, term->TI_sgr0) != 0)) + if (term->TI_rmso && (term->TI_sgr0 == NULL || g_strcmp0(term->TI_rmso, term->TI_sgr0) != 0)) g_string_append(str, term->TI_rmso); - if (term->TI_ritm && (term->TI_sgr0 == NULL || strcmp(term->TI_ritm, term->TI_sgr0) != 0)) + if (term->TI_ritm && (term->TI_sgr0 == NULL || g_strcmp0(term->TI_ritm, term->TI_sgr0) != 0)) g_string_append(str, term->TI_ritm); term->TI_normal = str->str; g_string_free(str, FALSE); @@ -659,10 +673,29 @@ static int term_setup(TERM_REC *term) term->beep = term->TI_bel ? _beep : _ignore; terminfo_setup_colors(term, FALSE); + terminfo_input_init0(term); terminfo_cont(term); return 1; } +void term_set_appkey_mode(int enable) +{ + if (current_term->appkey_enabled == enable) + return; + + current_term->appkey_enabled = enable; + terminfo_set_appkey_mode(current_term, enable); +} + +void term_set_bracketed_paste_mode(int enable) +{ + if (current_term->bracketed_paste_enabled == enable) + return; + + current_term->bracketed_paste_enabled = enable; + term_dec_set_bracketed_paste_mode(enable); +} + TERM_REC *terminfo_core_init(FILE *in, FILE *out) { TERM_REC *old_term, *term; |