Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/libbb/lineedit.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/libbb/lineedit.c

    r2725 r3232  
    4242#include "libbb.h"
    4343#include "unicode.h"
     44#ifndef _POSIX_VDISABLE
     45# define _POSIX_VDISABLE '\0'
     46#endif
     47
    4448
    4549#ifdef TEST
     
    185189    IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \
    186190} while (0)
     191
    187192static void deinit_S(void)
    188193{
     
    203208
    204209#if ENABLE_UNICODE_SUPPORT
    205 static size_t load_string(const char *src, int maxsize)
    206 {
    207     ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
    208     if (len < 0)
    209         len = 0;
    210     command_ps[len] = BB_NUL;
    211     return len;
     210static size_t load_string(const char *src)
     211{
     212    if (unicode_status == UNICODE_ON) {
     213        ssize_t len = mbstowcs(command_ps, src, S.maxsize - 1);
     214        if (len < 0)
     215            len = 0;
     216        command_ps[len] = BB_NUL;
     217        return len;
     218    } else {
     219        unsigned i = 0;
     220        while (src[i] && i < S.maxsize - 1) {
     221            command_ps[i] = src[i];
     222            i++;
     223        }
     224        command_ps[i] = BB_NUL;
     225        return i;
     226    }
    212227}
    213228static unsigned save_string(char *dst, unsigned maxsize)
    214229{
     230    if (unicode_status == UNICODE_ON) {
    215231# if !ENABLE_UNICODE_PRESERVE_BROKEN
    216     ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
    217     if (len < 0)
    218         len = 0;
    219     dst[len] = '\0';
    220     return len;
     232        ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
     233        if (len < 0)
     234            len = 0;
     235        dst[len] = '\0';
     236        return len;
    221237# else
    222     unsigned dstpos = 0;
    223     unsigned srcpos = 0;
    224 
    225     maxsize--;
    226     while (dstpos < maxsize) {
    227         wchar_t wc;
    228         int n = srcpos;
    229 
    230         /* Convert up to 1st invalid byte (or up to end) */
    231         while ((wc = command_ps[srcpos]) != BB_NUL
    232             && !unicode_is_raw_byte(wc)
    233         ) {
     238        unsigned dstpos = 0;
     239        unsigned srcpos = 0;
     240
     241        maxsize--;
     242        while (dstpos < maxsize) {
     243            wchar_t wc;
     244            int n = srcpos;
     245
     246            /* Convert up to 1st invalid byte (or up to end) */
     247            while ((wc = command_ps[srcpos]) != BB_NUL
     248                && !unicode_is_raw_byte(wc)
     249            ) {
     250                srcpos++;
     251            }
     252            command_ps[srcpos] = BB_NUL;
     253            n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
     254            if (n < 0) /* should not happen */
     255                break;
     256            dstpos += n;
     257            if (wc == BB_NUL) /* usually is */
     258                break;
     259
     260            /* We do have invalid byte here! */
     261            command_ps[srcpos] = wc; /* restore it */
    234262            srcpos++;
    235         }
    236         command_ps[srcpos] = BB_NUL;
    237         n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
    238         if (n < 0) /* should not happen */
    239             break;
    240         dstpos += n;
    241         if (wc == BB_NUL) /* usually is */
    242             break;
    243 
    244         /* We do have invalid byte here! */
    245         command_ps[srcpos] = wc; /* restore it */
    246         srcpos++;
    247         if (dstpos == maxsize)
    248             break;
    249         dst[dstpos++] = (char) wc;
    250     }
    251     dst[dstpos] = '\0';
    252     return dstpos;
     263            if (dstpos == maxsize)
     264                break;
     265            dst[dstpos++] = (char) wc;
     266        }
     267        dst[dstpos] = '\0';
     268        return dstpos;
    253269# endif
     270    } else {
     271        unsigned i = 0;
     272        while ((dst[i] = command_ps[i]) != 0)
     273            i++;
     274        return i;
     275    }
    254276}
    255277/* I thought just fputwc(c, stdout) would work. But no... */
    256278static void BB_PUTCHAR(wchar_t c)
    257279{
    258     char buf[MB_CUR_MAX + 1];
    259     mbstate_t mbst = { 0 };
    260     ssize_t len;
    261 
    262     len = wcrtomb(buf, c, &mbst);
    263     if (len > 0) {
    264         buf[len] = '\0';
    265         fputs(buf, stdout);
     280    if (unicode_status == UNICODE_ON) {
     281        char buf[MB_CUR_MAX + 1];
     282        mbstate_t mbst = { 0 };
     283        ssize_t len = wcrtomb(buf, c, &mbst);
     284        if (len > 0) {
     285            buf[len] = '\0';
     286            fputs(buf, stdout);
     287        }
     288    } else {
     289        /* In this case, c is always one byte */
     290        putchar(c);
    266291    }
    267292}
     
    298323}
    299324#else /* !UNICODE */
    300 static size_t load_string(const char *src, int maxsize)
    301 {
    302     safe_strncpy(command_ps, src, maxsize);
     325static size_t load_string(const char *src)
     326{
     327    safe_strncpy(command_ps, src, S.maxsize);
    303328    return strlen(command_ps);
    304329}
     
    12031228            /* where do we want to have cursor after all? */
    12041229            strcpy(&command[cursor_mb], chosen_match + match_pfx_len);
    1205             len = load_string(command, S.maxsize);
     1230            len = load_string(command);
    12061231            /* add match and tail */
    12071232            sprintf(&command[cursor_mb], "%s%s", chosen_match + match_pfx_len, match_buf);
    1208             command_len = load_string(command, S.maxsize);
     1233            command_len = load_string(command);
    12091234            /* write out the matched command */
    12101235            /* paranoia: load_string can return 0 on conv error,
     
    12271252    line_input_t *n = xzalloc(sizeof(*n));
    12281253    n->flags = flags;
     1254    n->max_history = MAX_HISTORY;
    12291255    return n;
    12301256}
     
    12321258
    12331259#if MAX_HISTORY > 0
     1260
     1261unsigned size_from_HISTFILESIZE(const char *hp)
     1262{
     1263    int size = MAX_HISTORY;
     1264    if (hp) {
     1265        size = atoi(hp);
     1266        if (size <= 0)
     1267            return 1;
     1268        if (size > MAX_HISTORY)
     1269            return MAX_HISTORY;
     1270    }
     1271    return size;
     1272}
    12341273
    12351274static void save_command_ps_at_cur_history(void)
     
    13131352        /* fill temp_h[], retaining only last MAX_HISTORY lines */
    13141353        memset(temp_h, 0, sizeof(temp_h));
    1315         st_parm->cnt_history_in_file = idx = 0;
     1354        idx = 0;
     1355        st_parm->cnt_history_in_file = 0;
    13161356        while ((line = xmalloc_fgetline(fp)) != NULL) {
    13171357            if (line[0] == '\0') {
     
    13231363            st_parm->cnt_history_in_file++;
    13241364            idx++;
    1325             if (idx == MAX_HISTORY)
     1365            if (idx == st_parm->max_history)
    13261366                idx = 0;
    13271367        }
     
    13321372            while (temp_h[idx] == NULL) {
    13331373                idx++;
    1334                 if (idx == MAX_HISTORY)
     1374                if (idx == st_parm->max_history)
    13351375                    idx = 0;
    13361376            }
     
    13381378
    13391379        /* copy temp_h[] to st_parm->history[] */
    1340         for (i = 0; i < MAX_HISTORY;) {
     1380        for (i = 0; i < st_parm->max_history;) {
    13411381            line = temp_h[idx];
    13421382            if (!line)
    13431383                break;
    13441384            idx++;
    1345             if (idx == MAX_HISTORY)
     1385            if (idx == st_parm->max_history)
    13461386                idx = 0;
    13471387            line_len = strlen(line);
     
    13511391        }
    13521392        st_parm->cnt_history = i;
    1353     }
    1354 }
    1355 
    1356 /* state->flags is already checked to be nonzero */
     1393        if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
     1394            st_parm->cnt_history_in_file = i;
     1395    }
     1396}
     1397
     1398#  if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
     1399void save_history(line_input_t *st)
     1400{
     1401    FILE *fp;
     1402
     1403    if (!st->hist_file)
     1404        return;
     1405    if (st->cnt_history <= st->cnt_history_in_file)
     1406        return;
     1407
     1408    fp = fopen(st->hist_file, "a");
     1409    if (fp) {
     1410        int i, fd;
     1411        char *new_name;
     1412        line_input_t *st_temp;
     1413
     1414        for (i = st->cnt_history_in_file; i < st->cnt_history; i++)
     1415            fprintf(fp, "%s\n", st->history[i]);
     1416        fclose(fp);
     1417
     1418        /* we may have concurrently written entries from others.
     1419         * load them */
     1420        st_temp = new_line_input_t(st->flags);
     1421        st_temp->hist_file = st->hist_file;
     1422        st_temp->max_history = st->max_history;
     1423        load_history(st_temp);
     1424
     1425        /* write out temp file and replace hist_file atomically */
     1426        new_name = xasprintf("%s.%u.new", st->hist_file, (int) getpid());
     1427        fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     1428        if (fd >= 0) {
     1429            fp = xfdopen_for_write(fd);
     1430            for (i = 0; i < st_temp->cnt_history; i++)
     1431                fprintf(fp, "%s\n", st_temp->history[i]);
     1432            fclose(fp);
     1433            if (rename(new_name, st->hist_file) == 0)
     1434                st->cnt_history_in_file = st_temp->cnt_history;
     1435        }
     1436        free(new_name);
     1437        free_line_input_t(st_temp);
     1438    }
     1439}
     1440#  else
    13571441static void save_history(char *str)
    13581442{
    13591443    int fd;
    13601444    int len, len2;
     1445
     1446    if (!state->hist_file)
     1447        return;
    13611448
    13621449    fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
     
    13741461    /* did we write so much that history file needs trimming? */
    13751462    state->cnt_history_in_file++;
    1376     if (state->cnt_history_in_file > MAX_HISTORY * 4) {
     1463    if (state->cnt_history_in_file > state->max_history * 4) {
    13771464        char *new_name;
    13781465        line_input_t *st_temp;
     
    13821469        st_temp = new_line_input_t(state->flags);
    13831470        st_temp->hist_file = state->hist_file;
     1471        st_temp->max_history = state->max_history;
    13841472        load_history(st_temp);
    13851473
    13861474        /* write out temp file and replace hist_file atomically */
    13871475        new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid());
    1388         fd = open(state->hist_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     1476        fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    13891477        if (fd >= 0) {
    13901478            FILE *fp;
     
    14021490    }
    14031491}
     1492#  endif
    14041493# else
    14051494#  define load_history(a) ((void)0)
     
    14201509        return;
    14211510
    1422     free(state->history[MAX_HISTORY]); /* redundant, paranoia */
    1423     state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
     1511    free(state->history[state->max_history]); /* redundant, paranoia */
     1512    state->history[state->max_history] = NULL; /* redundant, paranoia */
    14241513
    14251514    /* If history[] is full, remove the oldest command */
    1426     /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
    1427     if (i >= MAX_HISTORY) {
     1515    /* we need to keep history[state->max_history] empty, hence >=, not > */
     1516    if (i >= state->max_history) {
    14281517        free(state->history[0]);
    1429         for (i = 0; i < MAX_HISTORY-1; i++)
     1518        for (i = 0; i < state->max_history-1; i++)
    14301519            state->history[i] = state->history[i+1];
    1431         /* i == MAX_HISTORY-1 */
    1432     }
    1433     /* i <= MAX_HISTORY-1 */
     1520        /* i == state->max_history-1 */
     1521# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
     1522        if (state->cnt_history_in_file)
     1523            state->cnt_history_in_file--;
     1524# endif
     1525    }
     1526    /* i <= state->max_history-1 */
    14341527    state->history[i++] = xstrdup(str);
    1435     /* i <= MAX_HISTORY */
     1528    /* i <= state->max_history */
    14361529    state->cur_history = i;
    14371530    state->cnt_history = i;
    1438 # if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
    1439     if ((state->flags & SAVE_HISTORY) && state->hist_file)
    1440         save_history(str);
     1531# if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
     1532    save_history(str);
    14411533# endif
    14421534    IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
     
    16451737     * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout)  <-- no input exists
    16461738     * write(1, "\33[6n", 4) = 4  <-- send the ESC sequence, quick!
    1647      * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
     1739     * poll([{fd=0, events=POLLIN}], 1, -1) = 1 ([{fd=0, revents=POLLIN}])
    16481740     * read(0, "\n", 1)      = 1  <-- oh crap, user's input got in first
    16491741     */
     
    18031895    int sv_errno = errno;
    18041896    unsigned width;
     1897
    18051898    get_terminal_width_height(0, &width, NULL);
    1806     cmdedit_setwidth(width, nsig /* - just a yes/no flag */);
    1807     if (nsig == SIGWINCH)
    1808         signal(SIGWINCH, win_changed); /* rearm ourself */
     1899//FIXME: cmdedit_setwidth() -> redraw() -> printf() -> KABOOM! (we are in signal handler!)
     1900    cmdedit_setwidth(width, /*redraw_flg:*/ nsig);
     1901
    18091902    errno = sv_errno;
    18101903}
    18111904
    1812 static int lineedit_read_key(char *read_key_buffer)
     1905static int lineedit_read_key(char *read_key_buffer, int timeout)
    18131906{
    18141907    int64_t ic;
    1815     int timeout = -1;
    18161908#if ENABLE_UNICODE_SUPPORT
    18171909    char unicode_buf[MB_CUR_MAX + 1];
     
    19122004#define CTRL(a) ((a) & ~0x40)
    19132005
     2006enum {
     2007    VI_CMDMODE_BIT = 0x40000000,
     2008    /* 0x80000000 bit flags KEYCODE_xxx */
     2009};
     2010
     2011#if ENABLE_FEATURE_REVERSE_SEARCH
     2012/* Mimic readline Ctrl-R reverse history search.
     2013 * When invoked, it shows the following prompt:
     2014 * (reverse-i-search)'': user_input [cursor pos unchanged by Ctrl-R]
     2015 * and typing results in search being performed:
     2016 * (reverse-i-search)'tmp': cd /tmp [cursor under t in /tmp]
     2017 * Search is performed by looking at progressively older lines in history.
     2018 * Ctrl-R again searches for the next match in history.
     2019 * Backspace deletes last matched char.
     2020 * Control keys exit search and return to normal editing (at current history line).
     2021 */
     2022static int32_t reverse_i_search(void)
     2023{
     2024    char match_buf[128]; /* for user input */
     2025    char read_key_buffer[KEYCODE_BUFFER_SIZE];
     2026    const char *matched_history_line;
     2027    const char *saved_prompt;
     2028    int32_t ic;
     2029
     2030    matched_history_line = NULL;
     2031    read_key_buffer[0] = 0;
     2032    match_buf[0] = '\0';
     2033
     2034    /* Save and replace the prompt */
     2035    saved_prompt = cmdedit_prompt;
     2036    goto set_prompt;
     2037
     2038    while (1) {
     2039        int h;
     2040        unsigned match_buf_len = strlen(match_buf);
     2041
     2042        fflush_all();
     2043//FIXME: correct timeout?
     2044        ic = lineedit_read_key(read_key_buffer, -1);
     2045
     2046        switch (ic) {
     2047        case CTRL('R'): /* searching for the next match */
     2048            break;
     2049
     2050        case '\b':
     2051        case '\x7f':
     2052            /* Backspace */
     2053            if (unicode_status == UNICODE_ON) {
     2054                while (match_buf_len != 0) {
     2055                    uint8_t c = match_buf[--match_buf_len];
     2056                    if ((c & 0xc0) != 0x80) /* start of UTF-8 char? */
     2057                        break; /* yes */
     2058                }
     2059            } else {
     2060                if (match_buf_len != 0)
     2061                    match_buf_len--;
     2062            }
     2063            match_buf[match_buf_len] = '\0';
     2064            break;
     2065
     2066        default:
     2067            if (ic < ' '
     2068             || (!ENABLE_UNICODE_SUPPORT && ic >= 256)
     2069             || (ENABLE_UNICODE_SUPPORT && ic >= VI_CMDMODE_BIT)
     2070            ) {
     2071                goto ret;
     2072            }
     2073
     2074            /* Append this char */
     2075#if ENABLE_UNICODE_SUPPORT
     2076            if (unicode_status == UNICODE_ON) {
     2077                mbstate_t mbstate = { 0 };
     2078                char buf[MB_CUR_MAX + 1];
     2079                int len = wcrtomb(buf, ic, &mbstate);
     2080                if (len > 0) {
     2081                    buf[len] = '\0';
     2082                    if (match_buf_len + len < sizeof(match_buf))
     2083                        strcpy(match_buf + match_buf_len, buf);
     2084                }
     2085            } else
     2086#endif
     2087            if (match_buf_len < sizeof(match_buf) - 1) {
     2088                match_buf[match_buf_len] = ic;
     2089                match_buf[match_buf_len + 1] = '\0';
     2090            }
     2091            break;
     2092        } /* switch (ic) */
     2093
     2094        /* Search in history for match_buf */
     2095        h = state->cur_history;
     2096        if (ic == CTRL('R'))
     2097            h--;
     2098        while (h >= 0) {
     2099            if (state->history[h]) {
     2100                char *match = strstr(state->history[h], match_buf);
     2101                if (match) {
     2102                    state->cur_history = h;
     2103                    matched_history_line = state->history[h];
     2104                    command_len = load_string(matched_history_line);
     2105                    cursor = match - matched_history_line;
     2106//FIXME: cursor position for Unicode case
     2107
     2108                    free((char*)cmdedit_prompt);
     2109 set_prompt:
     2110                    cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
     2111                    cmdedit_prmt_len = strlen(cmdedit_prompt);
     2112                    goto do_redraw;
     2113                }
     2114            }
     2115            h--;
     2116        }
     2117
     2118        /* Not found */
     2119        match_buf[match_buf_len] = '\0';
     2120        beep();
     2121        continue;
     2122
     2123 do_redraw:
     2124        redraw(cmdedit_y, command_len - cursor);
     2125    } /* while (1) */
     2126
     2127 ret:
     2128    if (matched_history_line)
     2129        command_len = load_string(matched_history_line);
     2130
     2131    free((char*)cmdedit_prompt);
     2132    cmdedit_prompt = saved_prompt;
     2133    cmdedit_prmt_len = strlen(cmdedit_prompt);
     2134    redraw(cmdedit_y, command_len - cursor);
     2135
     2136    return ic;
     2137}
     2138#endif
     2139
    19142140/* maxsize must be >= 2.
    19152141 * Returns:
     
    19182144 * >0 length of input string, including terminating '\n'
    19192145 */
    1920 int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
     2146int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout)
    19212147{
    19222148    int len;
     
    19552181    S.maxsize = maxsize;
    19562182
    1957     /* With null flags, no other fields are ever used */
     2183    /* With zero flags, no other fields are ever used */
    19582184    state = st ? st : (line_input_t*) &const_int_0;
    19592185#if MAX_HISTORY > 0
    19602186# if ENABLE_FEATURE_EDITING_SAVEHISTORY
    1961     if ((state->flags & SAVE_HISTORY) && state->hist_file)
     2187    if (state->hist_file)
    19622188        if (state->cnt_history == 0)
    19632189            load_history(state);
     
    19792205
    19802206    new_settings = initial_settings;
    1981     new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
    1982     /* Turn off echoing and CTRL-C, so we can trap it */
    1983     new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
    1984     /* Hmm, in linux c_cc[] is not parsed if ICANON is off */
     2207    /* ~ICANON: unbuffered input (most c_cc[] are disabled, VMIN/VTIME are enabled) */
     2208    /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
     2209    /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
     2210    new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
     2211    /* reads would block only if < 1 char is available */
    19852212    new_settings.c_cc[VMIN] = 1;
     2213    /* no timeout (reads block forever) */
    19862214    new_settings.c_cc[VTIME] = 0;
    1987     /* Turn off CTRL-C, so we can trap it */
    1988 #ifndef _POSIX_VDISABLE
    1989 # define _POSIX_VDISABLE '\0'
    1990 #endif
    1991     new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
     2215    /* Should be not needed if ISIG is off: */
     2216    /* Turn off CTRL-C */
     2217    /* new_settings.c_cc[VINTR] = _POSIX_VDISABLE; */
    19922218    tcsetattr_stdin_TCSANOW(&new_settings);
    19932219
    1994     /* Now initialize things */
    1995     previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
    1996     win_changed(0); /* do initial resizing */
    19972220#if ENABLE_USERNAME_OR_HOMEDIR
    19982221    {
     
    20082231
    20092232#if 0
    2010     for (i = 0; i <= MAX_HISTORY; i++)
     2233    for (i = 0; i <= state->max_history; i++)
    20112234        bb_error_msg("history[%d]:'%s'", i, state->history[i]);
    20122235    bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
     
    20162239    parse_and_put_prompt(prompt);
    20172240    ask_terminal();
     2241
     2242    /* Install window resize handler (NB: after *all* init is complete) */
     2243//FIXME: save entire sigaction!
     2244    previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
     2245    win_changed(0); /* get initial window size */
    20182246
    20192247    read_key_buffer[0] = 0;
     
    20272255         * in one place.
    20282256         */
    2029         enum {
    2030             VI_CMDMODE_BIT = 0x40000000,
    2031             /* 0x80000000 bit flags KEYCODE_xxx */
    2032         };
    20332257        int32_t ic, ic_raw;
    20342258
    20352259        fflush_all();
    2036         ic = ic_raw = lineedit_read_key(read_key_buffer);
    2037 
     2260        ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
     2261
     2262#if ENABLE_FEATURE_REVERSE_SEARCH
     2263 again:
     2264#endif
    20382265#if ENABLE_FEATURE_EDITING_VI
    20392266        newdelflag = 1;
     
    21392366                input_backspace();
    21402367            break;
     2368#if ENABLE_FEATURE_REVERSE_SEARCH
     2369        case CTRL('R'):
     2370            ic = ic_raw = reverse_i_search();
     2371            goto again;
     2372#endif
    21412373
    21422374#if ENABLE_FEATURE_EDITING_VI
     
    21952427            int nc, sc;
    21962428
    2197             ic = lineedit_read_key(read_key_buffer);
     2429            ic = lineedit_read_key(read_key_buffer, timeout);
    21982430            if (errno) /* error */
    21992431                goto return_error_indicator;
     
    22592491        case 'r'|VI_CMDMODE_BIT:
    22602492//FIXME: unicode case?
    2261             ic = lineedit_read_key(read_key_buffer);
     2493            ic = lineedit_read_key(read_key_buffer, timeout);
    22622494            if (errno) /* error */
    22632495                goto return_error_indicator;
     
    22762508                input_backward(1);
    22772509            }
     2510            /* Handle a few ESC-<key> combinations the same way
     2511             * standard readline bindings (IOW: bash) do.
     2512             * Often, Alt-<key> generates ESC-<key>.
     2513             */
     2514            ic = lineedit_read_key(read_key_buffer, timeout);
     2515            switch (ic) {
     2516                //case KEYCODE_LEFT: - bash doesn't do this
     2517                case 'b':
     2518                    ctrl_left();
     2519                    break;
     2520                //case KEYCODE_RIGHT: - bash doesn't do this
     2521                case 'f':
     2522                    ctrl_right();
     2523                    break;
     2524                //case KEYCODE_DELETE: - bash doesn't do this
     2525                case 'd':  /* Alt-D */
     2526                {
     2527                    /* Delete word forward */
     2528                    int nc, sc = cursor;
     2529                    ctrl_right();
     2530                    nc = cursor - sc;
     2531                    input_backward(nc);
     2532                    while (--nc >= 0)
     2533                        input_delete(1);
     2534                    break;
     2535                }
     2536                case '\b':   /* Alt-Backspace(?) */
     2537                case '\x7f': /* Alt-Backspace(?) */
     2538                //case 'w': - bash doesn't do this
     2539                {
     2540                    /* Delete word backward */
     2541                    int sc = cursor;
     2542                    ctrl_left();
     2543                    while (sc-- > cursor)
     2544                        input_delete(1);
     2545                    break;
     2546                }
     2547            }
    22782548            break;
    22792549#endif /* FEATURE_COMMAND_EDITING_VI */
     
    22922562            /* change command */
    22932563            command_len = load_string(state->history[state->cur_history] ?
    2294                     state->history[state->cur_history] : "", maxsize);
     2564                    state->history[state->cur_history] : "");
    22952565            /* redraw and go to eol (bol, in vi) */
    22962566            redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
     
    23042574            break;
    23052575        case KEYCODE_CTRL_LEFT:
     2576        case KEYCODE_ALT_LEFT: /* bash doesn't do it */
    23062577            ctrl_left();
    23072578            break;
    23082579        case KEYCODE_CTRL_RIGHT:
     2580        case KEYCODE_ALT_RIGHT: /* bash doesn't do it */
    23092581            ctrl_right();
    23102582            break;
     
    24582730    fputs(prompt, stdout);
    24592731    fflush_all();
    2460     fgets(command, maxsize, stdin);
     2732    if (!fgets(command, maxsize, stdin))
     2733        return -1;
    24612734    return strlen(command);
    24622735}
Note: See TracChangeset for help on using the changeset viewer.