Merge tag 'mksh-R53' into HEAD

Conflicts:
    exec.c
This commit is contained in:
KO Myung-Hun
2016-08-13 15:05:49 +09:00
23 changed files with 1612 additions and 1024 deletions

474
edit.c
View File

@ -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 */