Changeset View
Changeset View
Standalone View
Standalone View
lib/libedit/tty.c
/* $NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $ */ | /* $NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 christos Exp $ */ | ||||
/*- | /*- | ||||
* Copyright (c) 1992, 1993 | * Copyright (c) 1992, 1993 | ||||
* The Regents of the University of California. All rights reserved. | * The Regents of the University of California. All rights reserved. | ||||
* | * | ||||
* This code is derived from software contributed to Berkeley by | * This code is derived from software contributed to Berkeley by | ||||
* Christos Zoulas of Cornell University. | * Christos Zoulas of Cornell University. | ||||
* | * | ||||
Show All 22 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "config.h" | #include "config.h" | ||||
#if !defined(lint) && !defined(SCCSID) | #if !defined(lint) && !defined(SCCSID) | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; | static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; | ||||
#else | #else | ||||
__RCSID("$NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $"); | __RCSID("$NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 christos Exp $"); | ||||
#endif | #endif | ||||
#endif /* not lint && not SCCSID */ | #endif /* not lint && not SCCSID */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
/* | /* | ||||
* tty.c: tty interface stuff | * tty.c: tty interface stuff | ||||
*/ | */ | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <stdlib.h> /* for abort */ | #include <stdlib.h> /* for abort */ | ||||
#include <string.h> | #include <string.h> | ||||
#include <strings.h> /* for ffs */ | #include <strings.h> /* for ffs */ | ||||
#include <unistd.h> /* for isatty */ | #include <unistd.h> /* for isatty */ | ||||
#include "el.h" | #include "el.h" | ||||
#include "fcns.h" | |||||
#include "parse.h" | #include "parse.h" | ||||
typedef struct ttymodes_t { | typedef struct ttymodes_t { | ||||
const char *m_name; | const char *m_name; | ||||
unsigned int m_value; | unsigned int m_value; | ||||
int m_type; | int m_type; | ||||
} ttymodes_t; | } ttymodes_t; | ||||
typedef struct ttymap_t { | typedef struct ttymap_t { | ||||
wint_t nch, och; /* Internal and termio rep of chars */ | wint_t nch, och; /* Internal and termio rep of chars */ | ||||
el_action_t bind[3]; /* emacs, vi, and vi-cmd */ | el_action_t bind[3]; /* emacs, vi, and vi-cmd */ | ||||
} ttymap_t; | } ttymap_t; | ||||
private const ttyperm_t ttyperm = { | static const ttyperm_t ttyperm = { | ||||
{ | { | ||||
{"iflag:", ICRNL, (INLCR | IGNCR)}, | {"iflag:", ICRNL, (INLCR | IGNCR)}, | ||||
{"oflag:", (OPOST | ONLCR), ONLRET}, | {"oflag:", (OPOST | ONLCR), ONLRET}, | ||||
{"cflag:", 0, 0}, | {"cflag:", 0, 0}, | ||||
{"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), | {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), | ||||
(NOFLSH | ECHONL | EXTPROC | FLUSHO)}, | (NOFLSH | ECHONL | EXTPROC | FLUSHO)}, | ||||
{"chars:", 0, 0}, | {"chars:", 0, 0}, | ||||
}, | }, | ||||
Show All 11 Lines | static const ttyperm_t ttyperm = { | ||||
{"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, | {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, | ||||
{"oflag:", 0, 0}, | {"oflag:", 0, 0}, | ||||
{"cflag:", 0, 0}, | {"cflag:", 0, 0}, | ||||
{"lflag:", 0, ISIG | IEXTEN}, | {"lflag:", 0, ISIG | IEXTEN}, | ||||
{"chars:", 0, 0}, | {"chars:", 0, 0}, | ||||
} | } | ||||
}; | }; | ||||
private const ttychar_t ttychar = { | static const ttychar_t ttychar = { | ||||
{ | { | ||||
CINTR, CQUIT, CERASE, CKILL, | CINTR, CQUIT, CERASE, CKILL, | ||||
CEOF, CEOL, CEOL2, CSWTCH, | CEOF, CEOL, CEOL2, CSWTCH, | ||||
CDSWTCH, CERASE2, CSTART, CSTOP, | CDSWTCH, CERASE2, CSTART, CSTOP, | ||||
CWERASE, CSUSP, CDSUSP, CREPRINT, | CWERASE, CSUSP, CDSUSP, CREPRINT, | ||||
CDISCARD, CLNEXT, CSTATUS, CPAGE, | CDISCARD, CLNEXT, CSTATUS, CPAGE, | ||||
CPGOFF, CKILL2, CBRK, CMIN, | CPGOFF, CKILL2, CBRK, CMIN, | ||||
CTIME | CTIME | ||||
Show All 13 Lines | static const ttychar_t ttychar = { | ||||
0, 0, 0, 0, | 0, 0, 0, 0, | ||||
0, 0, 0, 0, | 0, 0, 0, 0, | ||||
0, 0, 0, 0, | 0, 0, 0, 0, | ||||
0, 0, 0, 0, | 0, 0, 0, 0, | ||||
0 | 0 | ||||
} | } | ||||
}; | }; | ||||
private const ttymap_t tty_map[] = { | static const ttymap_t tty_map[] = { | ||||
#ifdef VERASE | #ifdef VERASE | ||||
{C_ERASE, VERASE, | {C_ERASE, VERASE, | ||||
{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, | {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, | ||||
#endif /* VERASE */ | #endif /* VERASE */ | ||||
#ifdef VERASE2 | #ifdef VERASE2 | ||||
{C_ERASE2, VERASE2, | {C_ERASE2, VERASE2, | ||||
{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, | {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, | ||||
#endif /* VERASE2 */ | #endif /* VERASE2 */ | ||||
Show All 20 Lines | |||||
#ifdef VLNEXT | #ifdef VLNEXT | ||||
{C_LNEXT, VLNEXT, | {C_LNEXT, VLNEXT, | ||||
{ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, | {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, | ||||
#endif /* VLNEXT */ | #endif /* VLNEXT */ | ||||
{(wint_t)-1, (wint_t)-1, | {(wint_t)-1, (wint_t)-1, | ||||
{ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} | {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} | ||||
}; | }; | ||||
private const ttymodes_t ttymodes[] = { | static const ttymodes_t ttymodes[] = { | ||||
#ifdef IGNBRK | #ifdef IGNBRK | ||||
{"ignbrk", IGNBRK, MD_INP}, | {"ignbrk", IGNBRK, MD_INP}, | ||||
#endif /* IGNBRK */ | #endif /* IGNBRK */ | ||||
#ifdef BRKINT | #ifdef BRKINT | ||||
{"brkint", BRKINT, MD_INP}, | {"brkint", BRKINT, MD_INP}, | ||||
#endif /* BRKINT */ | #endif /* BRKINT */ | ||||
#ifdef IGNPAR | #ifdef IGNPAR | ||||
{"ignpar", IGNPAR, MD_INP}, | {"ignpar", IGNPAR, MD_INP}, | ||||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) | #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) | ||||
#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) | #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) | ||||
#define tty__cooked_mode(td) ((td)->c_lflag & ICANON) | #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) | ||||
private int tty_getty(EditLine *, struct termios *); | static int tty_getty(EditLine *, struct termios *); | ||||
private int tty_setty(EditLine *, int, const struct termios *); | static int tty_setty(EditLine *, int, const struct termios *); | ||||
private int tty__getcharindex(int); | static int tty__getcharindex(int); | ||||
private void tty__getchar(struct termios *, unsigned char *); | static void tty__getchar(struct termios *, unsigned char *); | ||||
private void tty__setchar(struct termios *, unsigned char *); | static void tty__setchar(struct termios *, unsigned char *); | ||||
private speed_t tty__getspeed(struct termios *); | static speed_t tty__getspeed(struct termios *); | ||||
private int tty_setup(EditLine *); | static int tty_setup(EditLine *); | ||||
private void tty_setup_flags(EditLine *, struct termios *, int); | static void tty_setup_flags(EditLine *, struct termios *, int); | ||||
#define t_qu t_ts | #define t_qu t_ts | ||||
/* tty_getty(): | /* tty_getty(): | ||||
* Wrapper for tcgetattr to handle EINTR | * Wrapper for tcgetattr to handle EINTR | ||||
*/ | */ | ||||
private int | static int | ||||
tty_getty(EditLine *el, struct termios *t) | tty_getty(EditLine *el, struct termios *t) | ||||
{ | { | ||||
int rv; | int rv; | ||||
while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR) | while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR) | ||||
continue; | continue; | ||||
return rv; | return rv; | ||||
} | } | ||||
/* tty_setty(): | /* tty_setty(): | ||||
* Wrapper for tcsetattr to handle EINTR | * Wrapper for tcsetattr to handle EINTR | ||||
*/ | */ | ||||
private int | static int | ||||
tty_setty(EditLine *el, int action, const struct termios *t) | tty_setty(EditLine *el, int action, const struct termios *t) | ||||
{ | { | ||||
int rv; | int rv; | ||||
while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR) | while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR) | ||||
continue; | continue; | ||||
return rv; | return rv; | ||||
} | } | ||||
/* tty_setup(): | /* tty_setup(): | ||||
* Get the tty parameters and initialize the editing state | * Get the tty parameters and initialize the editing state | ||||
*/ | */ | ||||
private int | static int | ||||
tty_setup(EditLine *el) | tty_setup(EditLine *el) | ||||
{ | { | ||||
int rst = 1; | int rst = (el->el_flags & NO_RESET) == 0; | ||||
if (el->el_flags & EDIT_DISABLED) | if (el->el_flags & EDIT_DISABLED) | ||||
return 0; | return 0; | ||||
if (el->el_tty.t_initialized) | if (el->el_tty.t_initialized) | ||||
return -1; | return -1; | ||||
if (!isatty(el->el_outfd)) { | if (!isatty(el->el_outfd)) { | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | #endif /* DEBUG_TTY */ | ||||
tty_setup_flags(el, &el->el_tty.t_ed, ED_IO); | tty_setup_flags(el, &el->el_tty.t_ed, ED_IO); | ||||
tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); | tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); | ||||
tty_bind_char(el, 1); | tty_bind_char(el, 1); | ||||
el->el_tty.t_initialized = 1; | el->el_tty.t_initialized = 1; | ||||
return 0; | return 0; | ||||
} | } | ||||
protected int | libedit_private int | ||||
tty_init(EditLine *el) | tty_init(EditLine *el) | ||||
{ | { | ||||
el->el_tty.t_mode = EX_IO; | el->el_tty.t_mode = EX_IO; | ||||
el->el_tty.t_vdisable = _POSIX_VDISABLE; | el->el_tty.t_vdisable = _POSIX_VDISABLE; | ||||
el->el_tty.t_initialized = 0; | el->el_tty.t_initialized = 0; | ||||
(void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); | (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); | ||||
(void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); | (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); | ||||
return tty_setup(el); | return tty_setup(el); | ||||
} | } | ||||
/* tty_end(): | /* tty_end(): | ||||
* Restore the tty to its original settings | * Restore the tty to its original settings | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
tty_end(EditLine *el) | tty_end(EditLine *el, int how) | ||||
{ | { | ||||
if (el->el_flags & EDIT_DISABLED) | if (el->el_flags & EDIT_DISABLED) | ||||
return; | return; | ||||
if (!el->el_tty.t_initialized) | if (!el->el_tty.t_initialized) | ||||
return; | return; | ||||
if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) { | if (tty_setty(el, how, &el->el_tty.t_or) == -1) | ||||
{ | |||||
#ifdef DEBUG_TTY | #ifdef DEBUG_TTY | ||||
(void) fprintf(el->el_errfile, | (void) fprintf(el->el_errfile, | ||||
"%s: tty_setty: %s\n", __func__, strerror(errno)); | "%s: tty_setty: %s\n", __func__, strerror(errno)); | ||||
#endif /* DEBUG_TTY */ | #endif /* DEBUG_TTY */ | ||||
} | } | ||||
} | } | ||||
/* tty__getspeed(): | /* tty__getspeed(): | ||||
* Get the tty speed | * Get the tty speed | ||||
*/ | */ | ||||
private speed_t | static speed_t | ||||
tty__getspeed(struct termios *td) | tty__getspeed(struct termios *td) | ||||
{ | { | ||||
speed_t spd; | speed_t spd; | ||||
if ((spd = cfgetispeed(td)) == 0) | if ((spd = cfgetispeed(td)) == 0) | ||||
spd = cfgetospeed(td); | spd = cfgetospeed(td); | ||||
return spd; | return spd; | ||||
} | } | ||||
/* tty__getspeed(): | /* tty__getspeed(): | ||||
* Return the index of the asked char in the c_cc array | * Return the index of the asked char in the c_cc array | ||||
*/ | */ | ||||
private int | static int | ||||
tty__getcharindex(int i) | tty__getcharindex(int i) | ||||
{ | { | ||||
switch (i) { | switch (i) { | ||||
#ifdef VINTR | #ifdef VINTR | ||||
case C_INTR: | case C_INTR: | ||||
return VINTR; | return VINTR; | ||||
#endif /* VINTR */ | #endif /* VINTR */ | ||||
#ifdef VQUIT | #ifdef VQUIT | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | #endif /* VTIME */ | ||||
default: | default: | ||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
/* tty__getchar(): | /* tty__getchar(): | ||||
* Get the tty characters | * Get the tty characters | ||||
*/ | */ | ||||
private void | static void | ||||
tty__getchar(struct termios *td, unsigned char *s) | tty__getchar(struct termios *td, unsigned char *s) | ||||
{ | { | ||||
#ifdef VINTR | #ifdef VINTR | ||||
s[C_INTR] = td->c_cc[VINTR]; | s[C_INTR] = td->c_cc[VINTR]; | ||||
#endif /* VINTR */ | #endif /* VINTR */ | ||||
#ifdef VQUIT | #ifdef VQUIT | ||||
s[C_QUIT] = td->c_cc[VQUIT]; | s[C_QUIT] = td->c_cc[VQUIT]; | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | #ifdef VTIME | ||||
s[C_TIME] = td->c_cc[VTIME]; | s[C_TIME] = td->c_cc[VTIME]; | ||||
#endif /* VTIME */ | #endif /* VTIME */ | ||||
} /* tty__getchar */ | } /* tty__getchar */ | ||||
/* tty__setchar(): | /* tty__setchar(): | ||||
* Set the tty characters | * Set the tty characters | ||||
*/ | */ | ||||
private void | static void | ||||
tty__setchar(struct termios *td, unsigned char *s) | tty__setchar(struct termios *td, unsigned char *s) | ||||
{ | { | ||||
#ifdef VINTR | #ifdef VINTR | ||||
td->c_cc[VINTR] = s[C_INTR]; | td->c_cc[VINTR] = s[C_INTR]; | ||||
#endif /* VINTR */ | #endif /* VINTR */ | ||||
#ifdef VQUIT | #ifdef VQUIT | ||||
td->c_cc[VQUIT] = s[C_QUIT]; | td->c_cc[VQUIT] = s[C_QUIT]; | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | #ifdef VTIME | ||||
td->c_cc[VTIME] = s[C_TIME]; | td->c_cc[VTIME] = s[C_TIME]; | ||||
#endif /* VTIME */ | #endif /* VTIME */ | ||||
} /* tty__setchar */ | } /* tty__setchar */ | ||||
/* tty_bind_char(): | /* tty_bind_char(): | ||||
* Rebind the editline functions | * Rebind the editline functions | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
tty_bind_char(EditLine *el, int force) | tty_bind_char(EditLine *el, int force) | ||||
{ | { | ||||
unsigned char *t_n = el->el_tty.t_c[ED_IO]; | unsigned char *t_n = el->el_tty.t_c[ED_IO]; | ||||
unsigned char *t_o = el->el_tty.t_ed.c_cc; | unsigned char *t_o = el->el_tty.t_ed.c_cc; | ||||
Char new[2], old[2]; | wchar_t new[2], old[2]; | ||||
const ttymap_t *tp; | const ttymap_t *tp; | ||||
el_action_t *map, *alt; | el_action_t *map, *alt; | ||||
const el_action_t *dmap, *dalt; | const el_action_t *dmap, *dalt; | ||||
new[1] = old[1] = '\0'; | new[1] = old[1] = '\0'; | ||||
map = el->el_map.key; | map = el->el_map.key; | ||||
alt = el->el_map.alt; | alt = el->el_map.alt; | ||||
if (el->el_map.type == MAP_VI) { | if (el->el_map.type == MAP_VI) { | ||||
dmap = el->el_map.vii; | dmap = el->el_map.vii; | ||||
dalt = el->el_map.vic; | dalt = el->el_map.vic; | ||||
} else { | } else { | ||||
dmap = el->el_map.emacs; | dmap = el->el_map.emacs; | ||||
dalt = NULL; | dalt = NULL; | ||||
} | } | ||||
for (tp = tty_map; tp->nch != (wint_t)-1; tp++) { | for (tp = tty_map; tp->nch != (wint_t)-1; tp++) { | ||||
new[0] = (Char)t_n[tp->nch]; | new[0] = (wchar_t)t_n[tp->nch]; | ||||
old[0] = (Char)t_o[tp->och]; | old[0] = (wchar_t)t_o[tp->och]; | ||||
if (new[0] == old[0] && !force) | if (new[0] == old[0] && !force) | ||||
continue; | continue; | ||||
/* Put the old default binding back, and set the new binding */ | /* Put the old default binding back, and set the new binding */ | ||||
keymacro_clear(el, map, old); | keymacro_clear(el, map, old); | ||||
map[UC(old[0])] = dmap[UC(old[0])]; | map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]]; | ||||
keymacro_clear(el, map, new); | keymacro_clear(el, map, new); | ||||
/* MAP_VI == 1, MAP_EMACS == 0... */ | /* MAP_VI == 1, MAP_EMACS == 0... */ | ||||
map[UC(new[0])] = tp->bind[el->el_map.type]; | map[(unsigned char)new[0]] = tp->bind[el->el_map.type]; | ||||
if (dalt) { | if (dalt) { | ||||
keymacro_clear(el, alt, old); | keymacro_clear(el, alt, old); | ||||
alt[UC(old[0])] = dalt[UC(old[0])]; | alt[(unsigned char)old[0]] = | ||||
dalt[(unsigned char)old[0]]; | |||||
keymacro_clear(el, alt, new); | keymacro_clear(el, alt, new); | ||||
alt[UC(new[0])] = tp->bind[el->el_map.type + 1]; | alt[(unsigned char)new[0]] = | ||||
tp->bind[el->el_map.type + 1]; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
private tcflag_t * | static tcflag_t * | ||||
tty__get_flag(struct termios *t, int kind) { | tty__get_flag(struct termios *t, int kind) { | ||||
switch (kind) { | switch (kind) { | ||||
case MD_INP: | case MD_INP: | ||||
return &t->c_iflag; | return &t->c_iflag; | ||||
case MD_OUT: | case MD_OUT: | ||||
return &t->c_oflag; | return &t->c_oflag; | ||||
case MD_CTL: | case MD_CTL: | ||||
return &t->c_cflag; | return &t->c_cflag; | ||||
case MD_LIN: | case MD_LIN: | ||||
return &t->c_lflag; | return &t->c_lflag; | ||||
default: | default: | ||||
abort(); | abort(); | ||||
/*NOTREACHED*/ | /*NOTREACHED*/ | ||||
} | } | ||||
} | } | ||||
private tcflag_t | static tcflag_t | ||||
tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind) | tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind) | ||||
{ | { | ||||
f &= ~el->el_tty.t_t[mode][kind].t_clrmask; | f &= ~el->el_tty.t_t[mode][kind].t_clrmask; | ||||
f |= el->el_tty.t_t[mode][kind].t_setmask; | f |= el->el_tty.t_t[mode][kind].t_setmask; | ||||
return f; | return f; | ||||
} | } | ||||
private void | static void | ||||
tty_update_flags(EditLine *el, int kind) | tty_update_flags(EditLine *el, int kind) | ||||
{ | { | ||||
tcflag_t *tt, *ed, *ex; | tcflag_t *tt, *ed, *ex; | ||||
tt = tty__get_flag(&el->el_tty.t_ts, kind); | tt = tty__get_flag(&el->el_tty.t_ts, kind); | ||||
ed = tty__get_flag(&el->el_tty.t_ed, kind); | ed = tty__get_flag(&el->el_tty.t_ed, kind); | ||||
ex = tty__get_flag(&el->el_tty.t_ex, kind); | ex = tty__get_flag(&el->el_tty.t_ex, kind); | ||||
if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) { | if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) { | ||||
*ed = tty_update_flag(el, *tt, ED_IO, kind); | *ed = tty_update_flag(el, *tt, ED_IO, kind); | ||||
*ex = tty_update_flag(el, *tt, EX_IO, kind); | *ex = tty_update_flag(el, *tt, EX_IO, kind); | ||||
} | } | ||||
} | } | ||||
private void | static void | ||||
tty_update_char(EditLine *el, int mode, int c) { | tty_update_char(EditLine *el, int mode, int c) { | ||||
if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c))) | if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c))) | ||||
&& (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c])) | && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c])) | ||||
el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c]; | el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c]; | ||||
if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c)) | if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c)) | ||||
el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable; | el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable; | ||||
} | } | ||||
/* tty_rawmode(): | /* tty_rawmode(): | ||||
* Set terminal into 1 character at a time mode. | * Set terminal into 1 character at a time mode. | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
tty_rawmode(EditLine *el) | tty_rawmode(EditLine *el) | ||||
{ | { | ||||
if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) | if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) | ||||
return 0; | return 0; | ||||
if (el->el_flags & EDIT_DISABLED) | if (el->el_flags & EDIT_DISABLED) | ||||
return 0; | return 0; | ||||
Show All 38 Lines | if (tty__cooked_mode(&el->el_tty.t_ts)) { | ||||
*/ | */ | ||||
for (i = 0; i < C_NCC; i++) | for (i = 0; i < C_NCC; i++) | ||||
if (el->el_tty.t_c[TS_IO][i] != | if (el->el_tty.t_c[TS_IO][i] != | ||||
el->el_tty.t_c[EX_IO][i]) | el->el_tty.t_c[EX_IO][i]) | ||||
break; | break; | ||||
if (i != C_NCC) { | if (i != C_NCC) { | ||||
/* | /* | ||||
* Propagate changes only to the unprotected | * Propagate changes only to the unlibedit_private | ||||
* chars that have been modified just now. | * chars that have been modified just now. | ||||
*/ | */ | ||||
for (i = 0; i < C_NCC; i++) | for (i = 0; i < C_NCC; i++) | ||||
tty_update_char(el, ED_IO, i); | tty_update_char(el, ED_IO, i); | ||||
tty_bind_char(el, 0); | tty_bind_char(el, 0); | ||||
tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); | tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); | ||||
Show All 13 Lines | #endif /* DEBUG_TTY */ | ||||
el->el_tty.t_mode = ED_IO; | el->el_tty.t_mode = ED_IO; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* tty_cookedmode(): | /* tty_cookedmode(): | ||||
* Set the tty back to normal mode | * Set the tty back to normal mode | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
tty_cookedmode(EditLine *el) | tty_cookedmode(EditLine *el) | ||||
{ /* set tty in normal setup */ | { /* set tty in normal setup */ | ||||
if (el->el_tty.t_mode == EX_IO) | if (el->el_tty.t_mode == EX_IO) | ||||
return 0; | return 0; | ||||
if (el->el_flags & EDIT_DISABLED) | if (el->el_flags & EDIT_DISABLED) | ||||
return 0; | return 0; | ||||
if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { | if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { | ||||
#ifdef DEBUG_TTY | #ifdef DEBUG_TTY | ||||
(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, | (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, | ||||
strerror(errno)); | strerror(errno)); | ||||
#endif /* DEBUG_TTY */ | #endif /* DEBUG_TTY */ | ||||
return -1; | return -1; | ||||
} | } | ||||
el->el_tty.t_mode = EX_IO; | el->el_tty.t_mode = EX_IO; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* tty_quotemode(): | /* tty_quotemode(): | ||||
* Turn on quote mode | * Turn on quote mode | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
tty_quotemode(EditLine *el) | tty_quotemode(EditLine *el) | ||||
{ | { | ||||
if (el->el_tty.t_mode == QU_IO) | if (el->el_tty.t_mode == QU_IO) | ||||
return 0; | return 0; | ||||
el->el_tty.t_qu = el->el_tty.t_ed; | el->el_tty.t_qu = el->el_tty.t_ed; | ||||
tty_setup_flags(el, &el->el_tty.t_qu, QU_IO); | tty_setup_flags(el, &el->el_tty.t_qu, QU_IO); | ||||
if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { | if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { | ||||
#ifdef DEBUG_TTY | #ifdef DEBUG_TTY | ||||
(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, | (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, | ||||
strerror(errno)); | strerror(errno)); | ||||
#endif /* DEBUG_TTY */ | #endif /* DEBUG_TTY */ | ||||
return -1; | return -1; | ||||
} | } | ||||
el->el_tty.t_mode = QU_IO; | el->el_tty.t_mode = QU_IO; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* tty_noquotemode(): | /* tty_noquotemode(): | ||||
* Turn off quote mode | * Turn off quote mode | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
tty_noquotemode(EditLine *el) | tty_noquotemode(EditLine *el) | ||||
{ | { | ||||
if (el->el_tty.t_mode != QU_IO) | if (el->el_tty.t_mode != QU_IO) | ||||
return 0; | return 0; | ||||
if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { | if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { | ||||
#ifdef DEBUG_TTY | #ifdef DEBUG_TTY | ||||
(void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, | (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, | ||||
strerror(errno)); | strerror(errno)); | ||||
#endif /* DEBUG_TTY */ | #endif /* DEBUG_TTY */ | ||||
return -1; | return -1; | ||||
} | } | ||||
el->el_tty.t_mode = ED_IO; | el->el_tty.t_mode = ED_IO; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* tty_stty(): | /* tty_stty(): | ||||
* Stty builtin | * Stty builtin | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv) | tty_stty(EditLine *el, int argc __attribute__((__unused__)), | ||||
const wchar_t **argv) | |||||
{ | { | ||||
const ttymodes_t *m; | const ttymodes_t *m; | ||||
char x; | char x; | ||||
int aflag = 0; | int aflag = 0; | ||||
const Char *s, *d; | const wchar_t *s, *d; | ||||
char name[EL_BUFSIZ]; | char name[EL_BUFSIZ]; | ||||
struct termios *tios = &el->el_tty.t_ex; | struct termios *tios = &el->el_tty.t_ex; | ||||
int z = EX_IO; | int z = EX_IO; | ||||
if (argv == NULL) | if (argv == NULL) | ||||
return -1; | return -1; | ||||
strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); | strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); | ||||
name[sizeof(name) - 1] = '\0'; | name[sizeof(name) - 1] = '\0'; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | for (m = ttymodes; m->m_name; m++) { | ||||
(void) fprintf(el->el_outfile, "%s ", | (void) fprintf(el->el_outfile, "%s ", | ||||
m->m_name); | m->m_name); | ||||
} | } | ||||
} | } | ||||
(void) fprintf(el->el_outfile, "\n"); | (void) fprintf(el->el_outfile, "\n"); | ||||
return 0; | return 0; | ||||
} | } | ||||
while (argv && (s = *argv++)) { | while (argv && (s = *argv++)) { | ||||
const Char *p; | const wchar_t *p; | ||||
switch (*s) { | switch (*s) { | ||||
case '+': | case '+': | ||||
case '-': | case '-': | ||||
x = (char)*s++; | x = (char)*s++; | ||||
break; | break; | ||||
default: | default: | ||||
x = '\0'; | x = '\0'; | ||||
break; | break; | ||||
} | } | ||||
d = s; | d = s; | ||||
p = Strchr(s, '='); | p = wcschr(s, L'='); | ||||
for (m = ttymodes; m->m_name; m++) | for (m = ttymodes; m->m_name; m++) | ||||
if ((p ? strncmp(m->m_name, ct_encode_string(d, | if ((p ? strncmp(m->m_name, ct_encode_string(d, | ||||
&el->el_scratch), (size_t)(p - d)) : | &el->el_scratch), (size_t)(p - d)) : | ||||
strcmp(m->m_name, ct_encode_string(d, | strcmp(m->m_name, ct_encode_string(d, | ||||
&el->el_scratch))) == 0 && | &el->el_scratch))) == 0 && | ||||
(p == NULL || m->m_type == MD_CHAR)) | (p == NULL || m->m_type == MD_CHAR)) | ||||
break; | break; | ||||
if (!m->m_name) { | if (!m->m_name) { | ||||
(void) fprintf(el->el_errfile, | (void) fprintf(el->el_errfile, | ||||
"%s: Invalid argument `" FSTR "'.\n", name, d); | "%s: Invalid argument `%ls'.\n", name, d); | ||||
return -1; | return -1; | ||||
} | } | ||||
if (p) { | if (p) { | ||||
int c = ffs((int)m->m_value); | int c = ffs((int)m->m_value); | ||||
int v = *++p ? parse__escape(&p) : | int v = *++p ? parse__escape(&p) : | ||||
el->el_tty.t_vdisable; | el->el_tty.t_vdisable; | ||||
assert(c != 0); | assert(c != 0); | ||||
c--; | c--; | ||||
Show All 32 Lines | #endif /* DEBUG_TTY */ | ||||
return 0; | return 0; | ||||
} | } | ||||
#ifdef notyet | #ifdef notyet | ||||
/* tty_printchar(): | /* tty_printchar(): | ||||
* DEbugging routine to print the tty characters | * DEbugging routine to print the tty characters | ||||
*/ | */ | ||||
private void | static void | ||||
tty_printchar(EditLine *el, unsigned char *s) | tty_printchar(EditLine *el, unsigned char *s) | ||||
{ | { | ||||
ttyperm_t *m; | ttyperm_t *m; | ||||
int i; | int i; | ||||
for (i = 0; i < C_NCC; i++) { | for (i = 0; i < C_NCC; i++) { | ||||
for (m = el->el_tty.t_t; m->m_name; m++) | for (m = el->el_tty.t_t; m->m_name; m++) | ||||
if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) | if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) | ||||
break; | break; | ||||
if (m->m_name) | if (m->m_name) | ||||
(void) fprintf(el->el_errfile, "%s ^%c ", | (void) fprintf(el->el_errfile, "%s ^%c ", | ||||
m->m_name, s[i] + 'A' - 1); | m->m_name, s[i] + 'A' - 1); | ||||
if (i % 5 == 0) | if (i % 5 == 0) | ||||
(void) fprintf(el->el_errfile, "\n"); | (void) fprintf(el->el_errfile, "\n"); | ||||
} | } | ||||
(void) fprintf(el->el_errfile, "\n"); | (void) fprintf(el->el_errfile, "\n"); | ||||
} | } | ||||
#endif /* notyet */ | #endif /* notyet */ | ||||
private void | static void | ||||
tty_setup_flags(EditLine *el, struct termios *tios, int mode) | tty_setup_flags(EditLine *el, struct termios *tios, int mode) | ||||
{ | { | ||||
int kind; | int kind; | ||||
for (kind = MD_INP; kind <= MD_LIN; kind++) { | for (kind = MD_INP; kind <= MD_LIN; kind++) { | ||||
tcflag_t *f = tty__get_flag(tios, kind); | tcflag_t *f = tty__get_flag(tios, kind); | ||||
*f = tty_update_flag(el, *f, mode, kind); | *f = tty_update_flag(el, *f, mode, kind); | ||||
} | |||||
} | |||||
libedit_private int | |||||
tty_get_signal_character(EditLine *el, int sig) | |||||
{ | |||||
#ifdef ECHOCTL | |||||
tcflag_t *ed = tty__get_flag(&el->el_tty.t_ed, MD_INP); | |||||
if ((*ed & ECHOCTL) == 0) | |||||
return -1; | |||||
#endif | |||||
switch (sig) { | |||||
#ifdef SIGINT | |||||
case SIGINT: | |||||
return el->el_tty.t_c[ED_IO][VINTR]; | |||||
#endif | |||||
#ifdef SIGQUIT | |||||
case SIGQUIT: | |||||
return el->el_tty.t_c[ED_IO][VQUIT]; | |||||
#endif | |||||
#ifdef SIGINFO | |||||
case SIGINFO: | |||||
return el->el_tty.t_c[ED_IO][VSTATUS]; | |||||
#endif | |||||
#ifdef SIGTSTP | |||||
case SIGTSTP: | |||||
return el->el_tty.t_c[ED_IO][VSUSP]; | |||||
#endif | |||||
default: | |||||
return -1; | |||||
} | } | ||||
} | } |