/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013, 2014, 2015
+ * 2011, 2012, 2013, 2014, 2015, 2016
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#ifndef MKSH_NO_CMDLINE_EDITING
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.292 2015/10/09 16:11:13 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
#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;
-
-static X_chars edchars;
+#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;
+
+#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 */
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);
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 *);
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 +++ */
/* redraw line in Emacs mode */
xx_cols = x_cols;
x_init_prompt(false);
- x_e_rebuildline(MKSH_CLRTOEOL_STRING);
+ x_adjust();
}
}
#endif
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 };
/*
*--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;
source = s;
if (yylex(ONEWORD | LQCHAR) != LWORD) {
source = sold;
- internal_warningf("%s: %s", "fileglob", "bad substitution");
+ internal_warningf(Tfg_badsubst);
return (0);
}
source = sold;
/* 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() */
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
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);
* /// 2
* 0
*/
-static int
+static size_t
x_basename(const char *s, const char *se)
{
const char *p;
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;
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 **);
#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);
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;
#endif
#ifndef MKSH_SMALL
/* more non-standard ones */
+ { XFUNC_eval_region, 1, CTRL('E') },
{ XFUNC_edit_line, 2, 'e' }
#endif
};
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)
{
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);
}
/*x_goto(xcp);*/
x_adj_ok = true;
xlp_valid = false;
- cp = x_lastcp();
- while (cp > xcp)
- x_bs3(&cp);
-
+ x_lastpos();
x_modified();
return;
}
x_goto(char *cp)
{
cp = cp >= xep ? xep : x_bs0(cp, xbuf);
- if (cp < xbp || cp >= utf_skipcols(xbp, x_displen)) {
+ if (cp < xbp || cp >= utf_skipcols(xbp, x_displen, NULL)) {
/* we are heading off screen */
xcp = cp;
x_adjust();
}
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)
{
uint8_t c = *(unsigned 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('^');
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');
static void
x_load_hist(char **hp)
{
- int oldsize;
char *sp = NULL;
if (hp == histptr + 1) {
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;
}
}
}
if (offset < 0)
- x_redraw(-1);
+ x_redraw('\n');
return (KSTD);
}
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);
}
static int
x_draw_line(int c MKSH_A_UNUSED)
{
- x_redraw(-1);
+ x_redraw('\n');
return (KSTD);
}
static int
-x_e_rebuildline(const char *clrstr)
+x_cls(int c MKSH_A_UNUSED)
{
- shf_puts(clrstr, shl_out);
- x_adjust();
+ shf_puts(MKSH_CLS_STRING, shl_out);
+ x_redraw(0);
return (KSTD);
}
-static int
-x_cls(int c MKSH_A_UNUSED)
+/*
+ * 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_clrtoeol(int lastch, bool line_was_cleared)
{
- return (x_e_rebuildline(MKSH_CLS_STRING));
+ 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;
+ }
}
-/*
- * 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.
- */
+/* output the prompt, assuming a line has just been started */
static void
-x_redraw(int limit)
+x_pprompt(void)
{
- int i, j;
- char *cp;
+ 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
}
static void
-x_push(int nchars)
+x_push(size_t nchars)
{
afree(killstack[killsp], AEDIT);
strndupx(killstack[killsp], xcp, nchars, AEDIT);
killtp--;
if (killstack[killtp] == 0) {
x_e_puts("\nnothing to yank");
- x_redraw(-1);
+ x_redraw('\n');
return (KSTD);
}
xmp = xcp;
killstack[killtp] == 0) {
killtp = killsp;
x_e_puts("\nyank something first");
- x_redraw(-1);
+ x_redraw('\n');
return (KSTD);
}
len = strlen(killstack[killtp]);
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]);
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) {
m1 = msg;
while (*c && (size_t)(m1 - msg) < sizeof(msg) - 3)
x_mapout2(*c++, &m1);
- bi_errorf("%s: %s", "too long key sequence", msg);
+ bi_errorf("too long key sequence: %s", msg);
return (1);
}
#ifndef MKSH_SMALL
if (!strcmp(x_ftab[f].xf_name, a2))
break;
if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
- bi_errorf("%s: %s %s", a2, "no such", Tfunction);
+ bi_errorf("%s: no such function", a2);
return (1);
}
}
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);
}
*/
if (nwords == 1 && words[0][nlen - 1] != '/' &&
!(flags & XCF_IS_NOSPACE)) {
- x_ins(" ");
+ x_ins(T1space);
}
x_free_words(nwords, words);
x_adjust_out:
xlp_valid = false;
- x_redraw(xx_cols);
+ x_redraw('\r');
x_flush();
}
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);
xep = xbuf + len;
*xep = '\0';
xcp = xbp = xbuf;
- x_redraw(oldsize);
+ x_redraw('\r');
if (ret > 0)
return (x_newline('\n'));
}
{
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();
xbp = o_xbp;
xep = o_xep;
xcp = o_xcp;
- x_redraw((int)vlen);
+ x_redraw('\r');
if (c < 0)
return (KSTD);
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);
* 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)
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)
{
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
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);
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;
}
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]);
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;
{
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();
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],
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],
(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
argcnt++;
p++;
}
- if (putbuf(" ", 1, false) != 0 ||
+ if (putbuf(T1space, 1, false) != 0 ||
putbuf(sp, argcnt, false) != 0) {
if (es->cursor != 0)
es->cursor--;
static int
domove(int argcnt, const char *cmd, int sub)
{
- int bcount, i = 0, t;
- int ncursor = 0;
+ int ncursor = 0, i = 0, t;
+ unsigned int bcount;
switch (*cmd) {
case 'b':
ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
if (ksh_isalnux(es->cbuf[ncursor]))
- while (ksh_isalnux(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
+ while (ncursor < es->linelen &&
+ ksh_isalnux(es->cbuf[ncursor]))
ncursor++;
else if (!ksh_isspace(es->cbuf[ncursor]))
- while (!ksh_isalnux(es->cbuf[ncursor]) &&
- !ksh_isspace(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
+ while (ncursor < es->linelen &&
+ !ksh_isalnux(es->cbuf[ncursor]) &&
+ !ksh_isspace(es->cbuf[ncursor]))
ncursor++;
- while (ksh_isspace(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
+ while (ncursor < es->linelen &&
+ ksh_isspace(es->cbuf[ncursor]))
ncursor++;
}
return (ncursor);
ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
- while (!ksh_isspace(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
+ while (ncursor < es->linelen &&
+ !ksh_isspace(es->cbuf[ncursor]))
ncursor++;
- while (ksh_isspace(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
+ while (ncursor < es->linelen &&
+ ksh_isspace(es->cbuf[ncursor]))
ncursor++;
}
return (ncursor);
}
(void)histnum(n);
if ((hptr = *histpos()) == NULL) {
- internal_warningf("%s: %s", "grabhist", "bad history array");
+ internal_warningf("grabhist: bad history array");
return (-1);
}
if (save)
x_putc('\r');
x_putc('\n');
}
- if (prompt_trunc != -1)
- pprompt(prompt, prompt_trunc);
- x_col = pwidth;
+ x_pprompt();
morec = ' ';
}
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 {
rval = -1;
break;
}
- if (++i < nwords && putbuf(" ", 1, false) != 0) {
+ if (++i < nwords && putbuf(T1space, 1, false) != 0) {
rval = -1;
break;
}
*/
if (match_len > 0 && match[match_len - 1] != '/' &&
!(flags & XCF_IS_NOSPACE))
- rval = putbuf(" ", 1, false);
+ rval = putbuf(T1space, 1, false);
}
x_free_words(nwords, words);
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 */
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 */