Merge tag 'mksh-R53' into HEAD
Conflicts: exec.c
This commit is contained in:
474
edit.c
474
edit.c
@ -28,7 +28,7 @@
|
||||
|
||||
#ifndef MKSH_NO_CMDLINE_EDITING
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.296 2016/05/05 22:56:12 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.306 2016/08/01 18:42:40 tg Exp $");
|
||||
|
||||
/*
|
||||
* in later versions we might use libtermcap for this, but since external
|
||||
@ -39,21 +39,28 @@ __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.296 2016/05/05 22:56:12 tg Exp $");
|
||||
#ifndef MKSH_CLS_STRING
|
||||
#define MKSH_CLS_STRING "\033[;H\033[J"
|
||||
#endif
|
||||
#ifndef MKSH_CLRTOEOL_STRING
|
||||
#define MKSH_CLRTOEOL_STRING "\033[K"
|
||||
#endif
|
||||
|
||||
/* tty driver characters we are interested in */
|
||||
typedef struct {
|
||||
int erase;
|
||||
int kill;
|
||||
int werase;
|
||||
int intr;
|
||||
int quit;
|
||||
int eof;
|
||||
} X_chars;
|
||||
#define EDCHAR_DISABLED 0xFFFFU
|
||||
#define EDCHAR_INITIAL 0xFFFEU
|
||||
static struct {
|
||||
unsigned short erase;
|
||||
unsigned short kill;
|
||||
unsigned short werase;
|
||||
unsigned short intr;
|
||||
unsigned short quit;
|
||||
unsigned short eof;
|
||||
} edchars;
|
||||
|
||||
static X_chars edchars;
|
||||
#define isched(x,e) ((unsigned short)(unsigned char)(x) == (e))
|
||||
#define isedchar(x) (!((x) & ~0xFF))
|
||||
#ifndef _POSIX_VDISABLE
|
||||
#define toedchar(x) ((unsigned short)(unsigned char)(x))
|
||||
#else
|
||||
#define toedchar(x) (((_POSIX_VDISABLE != -1) && ((x) == _POSIX_VDISABLE)) ? \
|
||||
((unsigned short)EDCHAR_DISABLED) : \
|
||||
((unsigned short)(unsigned char)(x)))
|
||||
#endif
|
||||
|
||||
/* x_cf_glob() flags */
|
||||
#define XCF_COMMAND BIT(0) /* Do command completion */
|
||||
@ -68,6 +75,10 @@ static int xx_cols; /* for Emacs mode */
|
||||
static int modified; /* buffer has been "modified" */
|
||||
static char *holdbufp; /* place to hold last edit buffer */
|
||||
|
||||
/* 0=dumb 1=tmux (for now) */
|
||||
static bool x_term_mode;
|
||||
|
||||
static void x_adjust(void);
|
||||
static int x_getc(void);
|
||||
static void x_putcf(int);
|
||||
static void x_modified(void);
|
||||
@ -78,7 +89,7 @@ static int x_cf_glob(int *, const char *, int, int, int *, int *, char ***);
|
||||
static size_t x_longest_prefix(int, char * const *);
|
||||
static void x_glob_hlp_add_qchar(char *);
|
||||
static char *x_glob_hlp_tilde_and_rem_qchar(char *, bool);
|
||||
static int x_basename(const char *, const char *);
|
||||
static size_t x_basename(const char *, const char *);
|
||||
static void x_free_words(int, char **);
|
||||
static int x_escape(const char *, size_t, int (*)(const char *, size_t));
|
||||
static int x_emacs(char *);
|
||||
@ -102,7 +113,6 @@ static int x_command_glob(int, char *, char ***);
|
||||
static int x_locate_word(const char *, int, int, int *, bool *);
|
||||
|
||||
static int x_e_getmbc(char *);
|
||||
static int x_e_rebuildline(const char *);
|
||||
|
||||
/* +++ generic editing functions +++ */
|
||||
|
||||
@ -152,7 +162,7 @@ x_getc(void)
|
||||
/* redraw line in Emacs mode */
|
||||
xx_cols = x_cols;
|
||||
x_init_prompt(false);
|
||||
x_e_rebuildline(MKSH_CLRTOEOL_STRING);
|
||||
x_adjust();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -230,7 +240,7 @@ static void
|
||||
x_print_expansions(int nwords, char * const *words, bool is_command)
|
||||
{
|
||||
bool use_copy = false;
|
||||
int prefix_len;
|
||||
size_t prefix_len;
|
||||
XPtrV l = { NULL, 0, 0 };
|
||||
|
||||
/*
|
||||
@ -336,7 +346,7 @@ x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
|
||||
*--cp = '/';
|
||||
} else {
|
||||
/* ok, expand and replace */
|
||||
cp = shf_smprintf("%s/%s", dp, cp);
|
||||
cp = shf_smprintf(Tf_sSs, dp, cp);
|
||||
if (magic_flag)
|
||||
afree(s, ATEMP);
|
||||
s = cp;
|
||||
@ -439,8 +449,8 @@ x_file_glob(int *flagsp, char *toglob, char ***wordsp)
|
||||
/* Data structure used in x_command_glob() */
|
||||
struct path_order_info {
|
||||
char *word;
|
||||
int base;
|
||||
int path_order;
|
||||
size_t base;
|
||||
size_t path_order;
|
||||
};
|
||||
|
||||
/* Compare routine used in x_command_glob() */
|
||||
@ -451,8 +461,13 @@ path_order_cmp(const void *aa, const void *bb)
|
||||
const struct path_order_info *b = (const struct path_order_info *)bb;
|
||||
int t;
|
||||
|
||||
t = strcmp(a->word + a->base, b->word + b->base);
|
||||
return (t ? t : a->path_order - b->path_order);
|
||||
if ((t = strcmp(a->word + a->base, b->word + b->base)))
|
||||
return (t);
|
||||
if (a->path_order > b->path_order)
|
||||
return (1);
|
||||
if (a->path_order < b->path_order)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -475,7 +490,7 @@ x_command_glob(int flags, char *toglob, char ***wordsp)
|
||||
glob_table(pat, &w, &l->funs);
|
||||
|
||||
glob_path(flags, pat, &w, path);
|
||||
if ((fpath = str_val(global("FPATH"))) != null)
|
||||
if ((fpath = str_val(global(TFPATH))) != null)
|
||||
glob_path(flags, pat, &w, fpath);
|
||||
|
||||
nwords = XPsize(w);
|
||||
@ -720,7 +735,7 @@ x_free_words(int nwords, char **words)
|
||||
* /// 2
|
||||
* 0
|
||||
*/
|
||||
static int
|
||||
static size_t
|
||||
x_basename(const char *s, const char *se)
|
||||
{
|
||||
const char *p;
|
||||
@ -832,12 +847,11 @@ static int
|
||||
x_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t))
|
||||
{
|
||||
size_t add = 0, wlen = len;
|
||||
const char *ifs = str_val(local("IFS", 0));
|
||||
int rval = 0;
|
||||
|
||||
while (wlen - add > 0)
|
||||
if (vstrchr("\"#$&'()*:;<=>?[\\`{|}", s[add]) ||
|
||||
vstrchr(ifs, s[add])) {
|
||||
ctype(s[add], C_IFS)) {
|
||||
if (putbuf_func(s, add) != 0) {
|
||||
rval = -1;
|
||||
break;
|
||||
@ -965,7 +979,6 @@ static size_t x_fword(bool);
|
||||
static void x_goto(char *);
|
||||
static char *x_bs0(char *, char *) MKSH_A_PURE;
|
||||
static void x_bs3(char **);
|
||||
static int x_size_str(char *);
|
||||
static int x_size2(char *, char **);
|
||||
static void x_zots(char *);
|
||||
static void x_zotc3(char **);
|
||||
@ -976,12 +989,11 @@ static int x_search_dir(int);
|
||||
#endif
|
||||
static int x_match(char *, char *);
|
||||
static void x_redraw(int);
|
||||
static void x_push(int);
|
||||
static void x_push(size_t);
|
||||
static char *x_mapin(const char *, Area *);
|
||||
static char *x_mapout(int);
|
||||
static void x_mapout2(int, char **);
|
||||
static void x_print(int, int);
|
||||
static void x_adjust(void);
|
||||
static void x_e_ungetc(int);
|
||||
static int x_e_getc(void);
|
||||
static void x_e_putc2(int);
|
||||
@ -991,6 +1003,7 @@ static void x_e_puts(const char *);
|
||||
static int x_fold_case(int);
|
||||
#endif
|
||||
static char *x_lastcp(void);
|
||||
static void x_lastpos(void);
|
||||
static void do_complete(int, Comp_type);
|
||||
static size_t x_nb2nc(size_t) MKSH_A_PURE;
|
||||
|
||||
@ -1126,6 +1139,7 @@ static struct x_defbindings const x_defbindings[] = {
|
||||
#endif
|
||||
#ifndef MKSH_SMALL
|
||||
/* more non-standard ones */
|
||||
{ XFUNC_eval_region, 1, CTRL('E') },
|
||||
{ XFUNC_edit_line, 2, 'e' }
|
||||
#endif
|
||||
};
|
||||
@ -1187,6 +1201,12 @@ x_e_getmbc(char *sbuf)
|
||||
return (pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* minimum required space to work with on a line - if the prompt
|
||||
* leaves less space than this on a line, the prompt is truncated
|
||||
*/
|
||||
#define MIN_EDIT_SPACE 7
|
||||
|
||||
static void
|
||||
x_init_prompt(bool doprint)
|
||||
{
|
||||
@ -1379,15 +1399,9 @@ x_ins(const char *s)
|
||||
x_lastcp();
|
||||
x_adj_ok = tobool(xcp >= xlp);
|
||||
x_zots(cp);
|
||||
/* has x_adjust() been called? */
|
||||
if (adj == x_adj_done) {
|
||||
/* no */
|
||||
cp = xlp;
|
||||
while (cp > xcp)
|
||||
x_bs3(&cp);
|
||||
}
|
||||
if (xlp == xep - 1)
|
||||
x_redraw(xx_cols);
|
||||
if (adj == x_adj_done)
|
||||
/* x_adjust() has not been called */
|
||||
x_lastpos();
|
||||
x_adj_ok = true;
|
||||
return (0);
|
||||
}
|
||||
@ -1494,10 +1508,7 @@ x_delete(size_t nc, bool push)
|
||||
/*x_goto(xcp);*/
|
||||
x_adj_ok = true;
|
||||
xlp_valid = false;
|
||||
cp = x_lastcp();
|
||||
while (cp > xcp)
|
||||
x_bs3(&cp);
|
||||
|
||||
x_lastpos();
|
||||
x_modified();
|
||||
return;
|
||||
}
|
||||
@ -1616,15 +1627,6 @@ x_bs3(char **p)
|
||||
x_e_putc2('\b');
|
||||
}
|
||||
|
||||
static int
|
||||
x_size_str(char *cp)
|
||||
{
|
||||
int size = 0;
|
||||
while (*cp)
|
||||
size += x_size2(cp, &cp);
|
||||
return (size);
|
||||
}
|
||||
|
||||
static int
|
||||
x_size2(char *cp, char **dcp)
|
||||
{
|
||||
@ -1660,7 +1662,7 @@ x_zotc3(char **cp)
|
||||
|
||||
if (c == '\t') {
|
||||
/* Kludge, tabs are always four spaces. */
|
||||
x_e_puts(" ");
|
||||
x_e_puts(T4spaces);
|
||||
(*cp)++;
|
||||
} else if (ISCTRL(c) && /* but not C1 */ c < 0x80) {
|
||||
x_e_putc2('^');
|
||||
@ -1774,9 +1776,11 @@ x_newline(int c MKSH_A_UNUSED)
|
||||
static int
|
||||
x_end_of_text(int c MKSH_A_UNUSED)
|
||||
{
|
||||
char tmp = edchars.eof;
|
||||
char *cp = &tmp;
|
||||
unsigned char tmp;
|
||||
char *cp = (void *)&tmp;
|
||||
|
||||
tmp = isedchar(edchars.eof) ? (unsigned char)edchars.eof :
|
||||
(unsigned char)CTRL('D');
|
||||
x_zotc3(&cp);
|
||||
x_putc('\r');
|
||||
x_putc('\n');
|
||||
@ -1830,7 +1834,6 @@ x_goto_hist(int c MKSH_A_UNUSED)
|
||||
static void
|
||||
x_load_hist(char **hp)
|
||||
{
|
||||
int oldsize;
|
||||
char *sp = NULL;
|
||||
|
||||
if (hp == histptr + 1) {
|
||||
@ -1843,17 +1846,12 @@ x_load_hist(char **hp)
|
||||
if (sp == NULL)
|
||||
sp = *hp;
|
||||
x_histp = hp;
|
||||
oldsize = x_size_str(xbuf);
|
||||
if (modified)
|
||||
strlcpy(holdbufp, xbuf, LINE);
|
||||
strlcpy(xbuf, sp, xend - xbuf);
|
||||
xbp = xbuf;
|
||||
xep = xcp = xbuf + strlen(xbuf);
|
||||
xlp_valid = false;
|
||||
if (xep <= x_lastcp()) {
|
||||
x_redraw(oldsize);
|
||||
}
|
||||
x_goto(xep);
|
||||
x_adjust();
|
||||
modified = 0;
|
||||
}
|
||||
|
||||
@ -1956,7 +1954,7 @@ x_search_hist(int c)
|
||||
}
|
||||
}
|
||||
if (offset < 0)
|
||||
x_redraw(-1);
|
||||
x_redraw('\n');
|
||||
return (KSTD);
|
||||
}
|
||||
|
||||
@ -2031,18 +2029,13 @@ x_match(char *str, char *pat)
|
||||
static int
|
||||
x_del_line(int c MKSH_A_UNUSED)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
*xep = 0;
|
||||
i = xep - xbuf;
|
||||
j = x_size_str(xbuf);
|
||||
xcp = xbuf;
|
||||
x_push(i);
|
||||
x_push(xep - (xcp = xbuf));
|
||||
xlp = xbp = xep = xbuf;
|
||||
xlp_valid = true;
|
||||
*xcp = 0;
|
||||
xmp = NULL;
|
||||
x_redraw(j);
|
||||
x_redraw('\r');
|
||||
x_modified();
|
||||
return (KSTD);
|
||||
}
|
||||
@ -2064,89 +2057,82 @@ x_mv_begin(int c MKSH_A_UNUSED)
|
||||
static int
|
||||
x_draw_line(int c MKSH_A_UNUSED)
|
||||
{
|
||||
x_redraw(-1);
|
||||
return (KSTD);
|
||||
}
|
||||
|
||||
static int
|
||||
x_e_rebuildline(const char *clrstr)
|
||||
{
|
||||
shf_puts(clrstr, shl_out);
|
||||
x_adjust();
|
||||
x_redraw('\n');
|
||||
return (KSTD);
|
||||
}
|
||||
|
||||
static int
|
||||
x_cls(int c MKSH_A_UNUSED)
|
||||
{
|
||||
return (x_e_rebuildline(MKSH_CLS_STRING));
|
||||
shf_puts(MKSH_CLS_STRING, shl_out);
|
||||
x_redraw(0);
|
||||
return (KSTD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Redraw (part of) the line. If limit is < 0, the everything is redrawn
|
||||
* on a NEW line, otherwise limit is the screen column up to which needs
|
||||
* redrawing.
|
||||
* clear line from x_col (current cursor position) to xx_cols - 2,
|
||||
* then output lastch, then go back to x_col; if lastch is space,
|
||||
* clear with termcap instead of spaces, or not if line_was_cleared;
|
||||
* lastch MUST be an ASCII character with wcwidth(lastch) == 1
|
||||
*/
|
||||
static void
|
||||
x_redraw(int limit)
|
||||
x_clrtoeol(int lastch, bool line_was_cleared)
|
||||
{
|
||||
int i, j;
|
||||
char *cp;
|
||||
int col;
|
||||
|
||||
if (lastch == ' ' && !line_was_cleared && x_term_mode == 1) {
|
||||
shf_puts("\033[K", shl_out);
|
||||
line_was_cleared = true;
|
||||
}
|
||||
if (lastch == ' ' && line_was_cleared)
|
||||
return;
|
||||
|
||||
col = x_col;
|
||||
while (col < (xx_cols - 2)) {
|
||||
x_putc(' ');
|
||||
++col;
|
||||
}
|
||||
x_putc(lastch);
|
||||
++col;
|
||||
while (col > x_col) {
|
||||
x_putc('\b');
|
||||
--col;
|
||||
}
|
||||
}
|
||||
|
||||
/* output the prompt, assuming a line has just been started */
|
||||
static void
|
||||
x_pprompt(void)
|
||||
{
|
||||
if (prompt_trunc != -1)
|
||||
pprompt(prompt, prompt_trunc);
|
||||
x_col = pwidth;
|
||||
}
|
||||
|
||||
/* output CR, then redraw the line, clearing to EOL if needed (cr ≠ 0, LF) */
|
||||
static void
|
||||
x_redraw(int cr)
|
||||
{
|
||||
int lch;
|
||||
|
||||
x_adj_ok = false;
|
||||
if (limit == -1)
|
||||
x_e_putc2('\n');
|
||||
else
|
||||
x_e_putc2('\r');
|
||||
/* clear the line */
|
||||
x_e_putc2(cr ? cr : '\r');
|
||||
x_flush();
|
||||
if (xbp == xbuf) {
|
||||
if (prompt_trunc != -1)
|
||||
pprompt(prompt, prompt_trunc);
|
||||
x_col = pwidth;
|
||||
}
|
||||
/* display the prompt */
|
||||
if (xbp == xbuf)
|
||||
x_pprompt();
|
||||
x_displen = xx_cols - 2 - x_col;
|
||||
/* display the line content */
|
||||
xlp_valid = false;
|
||||
x_zots(xbp);
|
||||
if (xbp != xbuf || xep > xlp)
|
||||
limit = xx_cols;
|
||||
if (limit >= 0) {
|
||||
if (xep > xlp)
|
||||
/* we fill the line */
|
||||
i = 0;
|
||||
else {
|
||||
char *cpl = xbp;
|
||||
|
||||
i = limit;
|
||||
while (cpl < xlp)
|
||||
i -= x_size2(cpl, &cpl);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
while ((j < i) || (x_col < (xx_cols - 2))) {
|
||||
if (!(x_col < (xx_cols - 2)))
|
||||
break;
|
||||
x_e_putc2(' ');
|
||||
j++;
|
||||
}
|
||||
i = ' ';
|
||||
if (xep > xlp) {
|
||||
/* more off screen */
|
||||
if (xbp > xbuf)
|
||||
i = '*';
|
||||
else
|
||||
i = '>';
|
||||
} else if (xbp > xbuf)
|
||||
i = '<';
|
||||
x_e_putc2(i);
|
||||
j++;
|
||||
while (j--)
|
||||
x_e_putc2('\b');
|
||||
}
|
||||
cp = xlp;
|
||||
while (cp > xcp)
|
||||
x_bs3(&cp);
|
||||
/* check whether there is more off-screen */
|
||||
lch = xep > xlp ? (xbp > xbuf ? '*' : '>') : (xbp > xbuf) ? '<' : ' ';
|
||||
/* clear the rest of the line */
|
||||
x_clrtoeol(lch, !cr || cr == '\n');
|
||||
/* go back to actual cursor position */
|
||||
x_lastpos();
|
||||
x_adj_ok = true;
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2264,7 +2250,7 @@ x_kill(int c MKSH_A_UNUSED)
|
||||
}
|
||||
|
||||
static void
|
||||
x_push(int nchars)
|
||||
x_push(size_t nchars)
|
||||
{
|
||||
afree(killstack[killsp], AEDIT);
|
||||
strndupx(killstack[killsp], xcp, nchars, AEDIT);
|
||||
@ -2281,7 +2267,7 @@ x_yank(int c MKSH_A_UNUSED)
|
||||
killtp--;
|
||||
if (killstack[killtp] == 0) {
|
||||
x_e_puts("\nnothing to yank");
|
||||
x_redraw(-1);
|
||||
x_redraw('\n');
|
||||
return (KSTD);
|
||||
}
|
||||
xmp = xcp;
|
||||
@ -2298,7 +2284,7 @@ x_meta_yank(int c MKSH_A_UNUSED)
|
||||
killstack[killtp] == 0) {
|
||||
killtp = killsp;
|
||||
x_e_puts("\nyank something first");
|
||||
x_redraw(-1);
|
||||
x_redraw('\n');
|
||||
return (KSTD);
|
||||
}
|
||||
len = strlen(killstack[killtp]);
|
||||
@ -2447,7 +2433,7 @@ x_print(int prefix, int key)
|
||||
shprintf("%s%s = ", x_mapout(key), (f & 0x80) ? "~" : "");
|
||||
if (XFUNC_VALUE(f) != XFUNC_ins_string)
|
||||
#endif
|
||||
shprintf("%s\n", x_ftab[XFUNC_VALUE(f)].xf_name);
|
||||
shprintf(Tf_sN, x_ftab[XFUNC_VALUE(f)].xf_name);
|
||||
#ifndef MKSH_SMALL
|
||||
else
|
||||
shprintf("'%s'\n", x_atab[prefix][key]);
|
||||
@ -2479,7 +2465,7 @@ x_bind(const char *a1, const char *a2,
|
||||
if (list) {
|
||||
for (f = 0; f < NELEM(x_ftab); f++)
|
||||
if (!(x_ftab[f].xf_flags & XF_NOBIND))
|
||||
shprintf("%s\n", x_ftab[f].xf_name);
|
||||
shprintf(Tf_sN, x_ftab[f].xf_name);
|
||||
return (0);
|
||||
}
|
||||
if (a1 == NULL) {
|
||||
@ -2713,7 +2699,7 @@ x_expand(int c MKSH_A_UNUSED)
|
||||
i = 0;
|
||||
while (i < nwords) {
|
||||
if (x_escape(words[i], strlen(words[i]), x_do_ins) < 0 ||
|
||||
(++i < nwords && x_ins(" ") < 0)) {
|
||||
(++i < nwords && x_ins(T1space) < 0)) {
|
||||
x_e_putc2(7);
|
||||
return (KSTD);
|
||||
}
|
||||
@ -2798,7 +2784,7 @@ do_complete(
|
||||
*/
|
||||
if (nwords == 1 && !mksh_dirsep(words[0][nlen - 1]) &&
|
||||
!(flags & XCF_IS_NOSPACE)) {
|
||||
x_ins(" ");
|
||||
x_ins(T1space);
|
||||
}
|
||||
|
||||
x_free_words(nwords, words);
|
||||
@ -2858,7 +2844,7 @@ x_adjust(void)
|
||||
|
||||
x_adjust_out:
|
||||
xlp_valid = false;
|
||||
x_redraw(xx_cols);
|
||||
x_redraw('\r');
|
||||
x_flush();
|
||||
}
|
||||
|
||||
@ -3019,7 +3005,6 @@ x_set_arg(int c)
|
||||
static int
|
||||
x_comment(int c MKSH_A_UNUSED)
|
||||
{
|
||||
int oldsize = x_size_str(xbuf);
|
||||
ssize_t len = xep - xbuf;
|
||||
int ret = x_do_comment(xbuf, xend - xbuf, &len);
|
||||
|
||||
@ -3030,7 +3015,7 @@ x_comment(int c MKSH_A_UNUSED)
|
||||
xep = xbuf + len;
|
||||
*xep = '\0';
|
||||
xcp = xbp = xbuf;
|
||||
x_redraw(oldsize);
|
||||
x_redraw('\r');
|
||||
if (ret > 0)
|
||||
return (x_newline('\n'));
|
||||
}
|
||||
@ -3042,15 +3027,13 @@ x_version(int c MKSH_A_UNUSED)
|
||||
{
|
||||
char *o_xbuf = xbuf, *o_xend = xend;
|
||||
char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp;
|
||||
int lim = x_lastcp() - xbp;
|
||||
size_t vlen;
|
||||
char *v;
|
||||
|
||||
strdupx(v, KSH_VERSION, ATEMP);
|
||||
|
||||
xbuf = xbp = xcp = v;
|
||||
xend = xep = v + (vlen = strlen(v));
|
||||
x_redraw(lim);
|
||||
xend = xep = v + strlen(v);
|
||||
x_redraw('\r');
|
||||
x_flush();
|
||||
|
||||
c = x_e_getc();
|
||||
@ -3059,7 +3042,7 @@ x_version(int c MKSH_A_UNUSED)
|
||||
xbp = o_xbp;
|
||||
xep = o_xep;
|
||||
xcp = o_xcp;
|
||||
x_redraw((int)vlen);
|
||||
x_redraw('\r');
|
||||
|
||||
if (c < 0)
|
||||
return (KSTD);
|
||||
@ -3088,7 +3071,7 @@ x_edit_line(int c MKSH_A_UNUSED)
|
||||
x_arg = source->line - (histptr - x_histp);
|
||||
}
|
||||
if (x_arg)
|
||||
shf_snprintf(xbuf, xend - xbuf, "%s %d",
|
||||
shf_snprintf(xbuf, xend - xbuf, Tf_sd,
|
||||
"fc -e ${VISUAL:-${EDITOR:-vi}} --", x_arg);
|
||||
else
|
||||
strlcpy(xbuf, "fc -e ${VISUAL:-${EDITOR:-vi}} --", xend - xbuf);
|
||||
@ -3263,22 +3246,10 @@ x_fold_case(int c)
|
||||
* NAME:
|
||||
* x_lastcp - last visible char
|
||||
*
|
||||
* SYNOPSIS:
|
||||
* x_lastcp()
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* This function returns a pointer to that char in the
|
||||
* edit buffer that will be the last displayed on the
|
||||
* screen. The sequence:
|
||||
*
|
||||
* cp = x_lastcp();
|
||||
* while (cp > xcp)
|
||||
* x_bs3(&cp);
|
||||
*
|
||||
* Will position the cursor correctly on the screen.
|
||||
*
|
||||
* RETURN VALUE:
|
||||
* cp or NULL
|
||||
* screen.
|
||||
*/
|
||||
static char *
|
||||
x_lastcp(void)
|
||||
@ -3300,6 +3271,16 @@ x_lastcp(void)
|
||||
return (xlp);
|
||||
}
|
||||
|
||||
/* correctly position the cursor on the screen from end of visible area */
|
||||
static void
|
||||
x_lastpos(void)
|
||||
{
|
||||
char *cp = x_lastcp();
|
||||
|
||||
while (cp > xcp)
|
||||
x_bs3(&cp);
|
||||
}
|
||||
|
||||
static void
|
||||
x_mode(bool onoff)
|
||||
{
|
||||
@ -3312,13 +3293,13 @@ x_mode(bool onoff)
|
||||
if (onoff) {
|
||||
x_mkraw(tty_fd, NULL, false);
|
||||
|
||||
edchars.erase = tty_state.c_cc[VERASE];
|
||||
edchars.kill = tty_state.c_cc[VKILL];
|
||||
edchars.intr = tty_state.c_cc[VINTR];
|
||||
edchars.quit = tty_state.c_cc[VQUIT];
|
||||
edchars.eof = tty_state.c_cc[VEOF];
|
||||
edchars.erase = toedchar(tty_state.c_cc[VERASE]);
|
||||
edchars.kill = toedchar(tty_state.c_cc[VKILL]);
|
||||
edchars.intr = toedchar(tty_state.c_cc[VINTR]);
|
||||
edchars.quit = toedchar(tty_state.c_cc[VQUIT]);
|
||||
edchars.eof = toedchar(tty_state.c_cc[VEOF]);
|
||||
#ifdef VWERASE
|
||||
edchars.werase = tty_state.c_cc[VWERASE];
|
||||
edchars.werase = toedchar(tty_state.c_cc[VWERASE]);
|
||||
#else
|
||||
edchars.werase = 0;
|
||||
#endif
|
||||
@ -3336,33 +3317,17 @@ x_mode(bool onoff)
|
||||
if (!edchars.werase)
|
||||
edchars.werase = CTRL('W');
|
||||
|
||||
#ifdef _POSIX_VDISABLE
|
||||
/* Convert unset values to internal 'unset' value */
|
||||
if (edchars.erase == _POSIX_VDISABLE)
|
||||
edchars.erase = -1;
|
||||
if (edchars.kill == _POSIX_VDISABLE)
|
||||
edchars.kill = -1;
|
||||
if (edchars.intr == _POSIX_VDISABLE)
|
||||
edchars.intr = -1;
|
||||
if (edchars.quit == _POSIX_VDISABLE)
|
||||
edchars.quit = -1;
|
||||
if (edchars.eof == _POSIX_VDISABLE)
|
||||
edchars.eof = -1;
|
||||
if (edchars.werase == _POSIX_VDISABLE)
|
||||
edchars.werase = -1;
|
||||
#endif
|
||||
|
||||
if (edchars.erase >= 0) {
|
||||
if (isedchar(edchars.erase)) {
|
||||
bind_if_not_bound(0, edchars.erase, XFUNC_del_back);
|
||||
bind_if_not_bound(1, edchars.erase, XFUNC_del_bword);
|
||||
}
|
||||
if (edchars.kill >= 0)
|
||||
if (isedchar(edchars.kill))
|
||||
bind_if_not_bound(0, edchars.kill, XFUNC_del_line);
|
||||
if (edchars.werase >= 0)
|
||||
if (isedchar(edchars.werase))
|
||||
bind_if_not_bound(0, edchars.werase, XFUNC_del_bword);
|
||||
if (edchars.intr >= 0)
|
||||
if (isedchar(edchars.intr))
|
||||
bind_if_not_bound(0, edchars.intr, XFUNC_abort);
|
||||
if (edchars.quit >= 0)
|
||||
if (isedchar(edchars.quit))
|
||||
bind_if_not_bound(0, edchars.quit, XFUNC_noop);
|
||||
} else
|
||||
mksh_tcset(tty_fd, &tty_state);
|
||||
@ -3601,16 +3566,19 @@ x_vi(char *buf)
|
||||
if (c == -1)
|
||||
break;
|
||||
if (state != VLIT) {
|
||||
if (c == edchars.intr || c == edchars.quit) {
|
||||
if (isched(c, edchars.intr) ||
|
||||
isched(c, edchars.quit)) {
|
||||
/* pretend we got an interrupt */
|
||||
x_vi_zotc(c);
|
||||
x_flush();
|
||||
trapsig(c == edchars.intr ? SIGINT : SIGQUIT);
|
||||
trapsig(isched(c, edchars.intr) ?
|
||||
SIGINT : SIGQUIT);
|
||||
x_mode(false);
|
||||
unwind(LSHELL);
|
||||
} else if (c == edchars.eof && state != VVERSION) {
|
||||
} else if (isched(c, edchars.eof) &&
|
||||
state != VVERSION) {
|
||||
if (es->linelen == 0) {
|
||||
x_vi_zotc(edchars.eof);
|
||||
x_vi_zotc(c);
|
||||
c = -1;
|
||||
break;
|
||||
}
|
||||
@ -3797,7 +3765,7 @@ vi_hook(int ch)
|
||||
memcpy(srchpat, locpat, srchlen + 1);
|
||||
}
|
||||
state = VCMD;
|
||||
} else if (ch == edchars.erase || ch == CTRL('h')) {
|
||||
} else if (isched(ch, edchars.erase) || ch == CTRL('h')) {
|
||||
if (srchlen != 0) {
|
||||
srchlen--;
|
||||
es->linelen -= char_len(locpat[srchlen]);
|
||||
@ -3808,13 +3776,13 @@ vi_hook(int ch)
|
||||
restore_cbuf();
|
||||
state = VNORMAL;
|
||||
refresh(0);
|
||||
} else if (ch == edchars.kill) {
|
||||
} else if (isched(ch, edchars.kill)) {
|
||||
srchlen = 0;
|
||||
es->linelen = 1;
|
||||
es->cursor = 1;
|
||||
refresh(0);
|
||||
return (0);
|
||||
} else if (ch == edchars.werase) {
|
||||
} else if (isched(ch, edchars.werase)) {
|
||||
unsigned int i, n;
|
||||
struct edstate new_es, *save_es;
|
||||
|
||||
@ -3968,7 +3936,7 @@ vi_insert(int ch)
|
||||
{
|
||||
int tcursor;
|
||||
|
||||
if (ch == edchars.erase || ch == CTRL('h')) {
|
||||
if (isched(ch, edchars.erase) || ch == CTRL('h')) {
|
||||
if (insert == REPLACE) {
|
||||
if (es->cursor == undo->cursor) {
|
||||
vi_error();
|
||||
@ -3994,7 +3962,7 @@ vi_insert(int ch)
|
||||
expanded = NONE;
|
||||
return (0);
|
||||
}
|
||||
if (ch == edchars.kill) {
|
||||
if (isched(ch, edchars.kill)) {
|
||||
if (es->cursor != 0) {
|
||||
inslen = 0;
|
||||
memmove(es->cbuf, &es->cbuf[es->cursor],
|
||||
@ -4005,7 +3973,7 @@ vi_insert(int ch)
|
||||
expanded = NONE;
|
||||
return (0);
|
||||
}
|
||||
if (ch == edchars.werase) {
|
||||
if (isched(ch, edchars.werase)) {
|
||||
if (es->cursor != 0) {
|
||||
tcursor = backword(1);
|
||||
memmove(&es->cbuf[tcursor], &es->cbuf[es->cursor],
|
||||
@ -4376,7 +4344,7 @@ vi_cmd(int argcnt, const char *cmd)
|
||||
(hlast - hnum);
|
||||
}
|
||||
if (argcnt)
|
||||
shf_snprintf(es->cbuf, es->cbufsize, "%s %d",
|
||||
shf_snprintf(es->cbuf, es->cbufsize, Tf_sd,
|
||||
"fc -e ${VISUAL:-${EDITOR:-vi}} --",
|
||||
argcnt);
|
||||
else
|
||||
@ -4505,7 +4473,7 @@ vi_cmd(int argcnt, const char *cmd)
|
||||
argcnt++;
|
||||
p++;
|
||||
}
|
||||
if (putbuf(" ", 1, false) != 0 ||
|
||||
if (putbuf(T1space, 1, false) != 0 ||
|
||||
putbuf(sp, argcnt, false) != 0) {
|
||||
if (es->cursor != 0)
|
||||
es->cursor--;
|
||||
@ -5110,9 +5078,7 @@ redraw_line(bool newl)
|
||||
x_putc('\r');
|
||||
x_putc('\n');
|
||||
}
|
||||
if (prompt_trunc != -1)
|
||||
pprompt(prompt, prompt_trunc);
|
||||
x_col = pwidth;
|
||||
x_pprompt();
|
||||
morec = ' ';
|
||||
}
|
||||
|
||||
@ -5267,9 +5233,7 @@ ed_mov_opt(int col, char *wb)
|
||||
if (col < x_col) {
|
||||
if (col + 1 < x_col - col) {
|
||||
x_putc('\r');
|
||||
if (prompt_trunc != -1)
|
||||
pprompt(prompt, prompt_trunc);
|
||||
x_col = pwidth;
|
||||
x_pprompt();
|
||||
while (x_col++ < col)
|
||||
x_putcf(*wb++);
|
||||
} else {
|
||||
@ -5323,7 +5287,7 @@ expand_word(int cmd)
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
if (++i < nwords && putbuf(" ", 1, false) != 0) {
|
||||
if (++i < nwords && putbuf(T1space, 1, false) != 0) {
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
@ -5441,7 +5405,7 @@ complete_word(int cmd, int count)
|
||||
*/
|
||||
if (match_len > 0 && !mksh_dirsep(match[match_len - 1]) &&
|
||||
!(flags & XCF_IS_NOSPACE))
|
||||
rval = putbuf(" ", 1, false);
|
||||
rval = putbuf(T1space, 1, false);
|
||||
}
|
||||
x_free_words(nwords, words);
|
||||
|
||||
@ -5511,12 +5475,11 @@ x_init(void)
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* Set edchars to -2 to force initial binding, except
|
||||
* we need default values for some deficient systems…
|
||||
* set edchars to force initial binding, except we need
|
||||
* default values for ^W for some deficient systems…
|
||||
*/
|
||||
edchars.erase = edchars.kill = edchars.intr = edchars.quit =
|
||||
edchars.eof = -2;
|
||||
/* ^W */
|
||||
edchars.eof = EDCHAR_INITIAL;
|
||||
edchars.werase = 027;
|
||||
|
||||
/* command line editing specific memory allocation */
|
||||
@ -5552,4 +5515,89 @@ x_done(void)
|
||||
afreeall(AEDIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
x_initterm(const char *termtype)
|
||||
{
|
||||
/* default must be 0 (bss) */
|
||||
x_term_mode = 0;
|
||||
/* this is what tmux uses, don't ask me about it */
|
||||
if (!strcmp(termtype, "screen") || !strncmp(termtype, "screen-", 7))
|
||||
x_term_mode = 1;
|
||||
}
|
||||
|
||||
#ifndef MKSH_SMALL
|
||||
static char *
|
||||
x_eval_region_helper(const char *cmd, size_t len)
|
||||
{
|
||||
char * volatile cp;
|
||||
newenv(E_ERRH);
|
||||
|
||||
if (!kshsetjmp(e->jbuf)) {
|
||||
char *wds = alloc(len + 3, ATEMP);
|
||||
|
||||
wds[0] = FUNSUB;
|
||||
memcpy(wds + 1, cmd, len);
|
||||
wds[len + 1] = '\0';
|
||||
wds[len + 2] = EOS;
|
||||
|
||||
cp = evalstr(wds, DOSCALAR);
|
||||
strdupx(cp, cp, AEDIT);
|
||||
} else
|
||||
cp = NULL;
|
||||
quitenv(NULL);
|
||||
return (cp);
|
||||
}
|
||||
|
||||
static int
|
||||
x_eval_region(int c MKSH_A_UNUSED)
|
||||
{
|
||||
char *evbeg, *evend, *cp;
|
||||
size_t newlen;
|
||||
/* only for LINE overflow checking */
|
||||
size_t restlen;
|
||||
|
||||
if (xmp == NULL) {
|
||||
evbeg = xbuf;
|
||||
evend = xep;
|
||||
} else if (xmp < xcp) {
|
||||
evbeg = xmp;
|
||||
evend = xcp;
|
||||
} else {
|
||||
evbeg = xcp;
|
||||
evend = xmp;
|
||||
}
|
||||
|
||||
x_e_putc2('\r');
|
||||
x_clrtoeol(' ', false);
|
||||
x_flush();
|
||||
x_mode(false);
|
||||
cp = x_eval_region_helper(evbeg, evend - evbeg);
|
||||
x_mode(true);
|
||||
|
||||
if (cp == NULL) {
|
||||
/* command cannot be parsed */
|
||||
x_eval_region_err:
|
||||
x_e_putc2(7);
|
||||
x_redraw('\r');
|
||||
return (KSTD);
|
||||
}
|
||||
|
||||
newlen = strlen(cp);
|
||||
restlen = xep - evend;
|
||||
/* check for LINE overflow, until this is dynamically allocated */
|
||||
if (evbeg + newlen + restlen >= xend)
|
||||
goto x_eval_region_err;
|
||||
|
||||
xmp = evbeg;
|
||||
xcp = evbeg + newlen;
|
||||
xep = xcp + restlen;
|
||||
memmove(xcp, evend, restlen + /* NUL */ 1);
|
||||
memcpy(xmp, cp, newlen);
|
||||
afree(cp, AEDIT);
|
||||
x_adjust();
|
||||
x_modified();
|
||||
return (KSTD);
|
||||
}
|
||||
#endif /* !MKSH_SMALL */
|
||||
#endif /* !MKSH_NO_CMDLINE_EDITING */
|
||||
|
Reference in New Issue
Block a user