mirror of
https://github.com/troglobit/editline.git
synced 2025-05-06 04:21:24 +08:00
Merge branch 'simple_multiline' of https://github.com/echoprotocol/editline into echoprotocol-simple_multiline
This commit is contained in:
commit
f35af9f20d
546
src/editline.c
546
src/editline.c
@ -113,6 +113,9 @@ static int Searching = 0;
|
|||||||
static const char *(*search_move)(void);
|
static const char *(*search_move)(void);
|
||||||
static const char *old_prompt = NULL;
|
static const char *old_prompt = NULL;
|
||||||
static rl_vcpfunc_t *line_handler = NULL;
|
static rl_vcpfunc_t *line_handler = NULL;
|
||||||
|
static char *line_up = "\x1b[A";
|
||||||
|
static char *line_down = "\x1b[B";
|
||||||
|
int prompt_len = 0;
|
||||||
|
|
||||||
int el_no_echo = 0; /* e.g., under Emacs */
|
int el_no_echo = 0; /* e.g., under Emacs */
|
||||||
int el_no_hist = 0;
|
int el_no_hist = 0;
|
||||||
@ -142,11 +145,11 @@ extern int tgetnum(const char *);
|
|||||||
static int is_alpha_num(unsigned char c)
|
static int is_alpha_num(unsigned char c)
|
||||||
{
|
{
|
||||||
if (isalnum(c))
|
if (isalnum(c))
|
||||||
return 1;
|
return 1;
|
||||||
if (ISMETA(c))
|
if (ISMETA(c))
|
||||||
return 1;
|
return 1;
|
||||||
if (ISCTL(c))
|
if (ISCTL(c))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -160,19 +163,19 @@ static void tty_flush(void)
|
|||||||
ssize_t res;
|
ssize_t res;
|
||||||
|
|
||||||
if (!ScreenCount)
|
if (!ScreenCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!el_no_echo) {
|
if (!el_no_echo) {
|
||||||
res = write(el_outfd, Screen, ScreenCount);
|
res = write(el_outfd, Screen, ScreenCount);
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
ScreenCount = 0;
|
ScreenCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tty_put(const char c)
|
static void tty_put(const char c)
|
||||||
{
|
{
|
||||||
if (el_no_echo)
|
if (el_no_echo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Screen[ScreenCount] = c;
|
Screen[ScreenCount] = c;
|
||||||
if (++ScreenCount >= ScreenSize) {
|
if (++ScreenCount >= ScreenSize) {
|
||||||
@ -206,8 +209,12 @@ static void tty_show(unsigned char c)
|
|||||||
|
|
||||||
static void tty_string(char *p)
|
static void tty_string(char *p)
|
||||||
{
|
{
|
||||||
while (*p)
|
int i = rl_point + prompt_len + 1;
|
||||||
|
while (*p) {
|
||||||
tty_show(*p++);
|
tty_show(*p++);
|
||||||
|
if ((i++) % tty_cols == 0)
|
||||||
|
tty_put('\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tty_push(int c)
|
static void tty_push(int c)
|
||||||
@ -222,7 +229,7 @@ int rl_getc(void)
|
|||||||
char c;
|
char c;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
r = read(el_infd, &c, 1);
|
r = read(el_infd, &c, 1);
|
||||||
} while (r == -1 && errno == EINTR);
|
} while (r == -1 && errno == EINTR);
|
||||||
|
|
||||||
return r == 1 ? c : EOF;
|
return r == 1 ? c : EOF;
|
||||||
@ -292,7 +299,8 @@ void el_print_columns(int ac, char **av)
|
|||||||
longest = j;
|
longest = j;
|
||||||
}
|
}
|
||||||
colwidth = longest + 3;
|
colwidth = longest + 3;
|
||||||
if (colwidth > tty_cols) colwidth = tty_cols;
|
if (colwidth > tty_cols)
|
||||||
|
colwidth = tty_cols;
|
||||||
cols = tty_cols / colwidth;
|
cols = tty_cols / colwidth;
|
||||||
|
|
||||||
tty_puts(NEWLINE);
|
tty_puts(NEWLINE);
|
||||||
@ -304,33 +312,90 @@ void el_print_columns(int ac, char **av)
|
|||||||
if (j + skip < ac) {
|
if (j + skip < ac) {
|
||||||
while (++len < colwidth)
|
while (++len < colwidth)
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_puts(NEWLINE);
|
tty_puts(NEWLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reposition(void)
|
static void reposition(int key)
|
||||||
{
|
{
|
||||||
int i;
|
int i = 0;
|
||||||
|
int len_with_prompt = prompt_len + rl_end;
|
||||||
|
int n = len_with_prompt / tty_cols; // determine the number of lines
|
||||||
|
|
||||||
tty_put('\r');
|
tty_put('\r');
|
||||||
tty_puts(rl_prompt);
|
|
||||||
for (i = 0; i < rl_point; i++)
|
if (n > 0) {
|
||||||
|
int line;
|
||||||
|
if (key == CTL('A') || key == CTL('E') || key == rl_kill)
|
||||||
|
line = (prompt_len + old_point) / tty_cols; // determine num of current line
|
||||||
|
else
|
||||||
|
line = len_with_prompt / tty_cols;
|
||||||
|
|
||||||
|
if (key == CTL('E')) { // move to end of line(s)
|
||||||
|
for(int k = line; k < n; k++)
|
||||||
|
tty_puts(line_down);
|
||||||
|
i = rl_point - (len_with_prompt % tty_cols); // determine reminder of last line and redraw only it
|
||||||
|
} else {
|
||||||
|
for(int k = line; k > 0; k--) // CTRL-A, CTRL-U, insert (end, middle), remove (end, middle)
|
||||||
|
tty_puts(line_up); // redraw characters until changed data
|
||||||
|
tty_puts(rl_prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (n == 0) {
|
||||||
|
tty_puts(rl_prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i; i < rl_point; i++) {
|
||||||
tty_show(rl_line_buffer[i]);
|
tty_show(rl_line_buffer[i]);
|
||||||
|
if ((i + prompt_len + 1) % tty_cols == 0) { // move to the next line
|
||||||
|
tty_put('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void itoa(int val, char* buf)
|
||||||
|
{
|
||||||
|
int digits = 0;
|
||||||
|
int temp = val;
|
||||||
|
while (temp != 0) {
|
||||||
|
temp = temp / 10;
|
||||||
|
++digits;
|
||||||
|
}
|
||||||
|
*(buf+digits) = 'C';
|
||||||
|
int i = 5; digits--;
|
||||||
|
for(; val && i ; --i, val /= 10) {
|
||||||
|
*(buf+digits) = "0123456789"[val % 10];
|
||||||
|
digits--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void move_cursor_forward(int columns)
|
||||||
|
{
|
||||||
|
char buf[12] = {0};
|
||||||
|
const char* line_forward = "\x1b[";
|
||||||
|
strcpy(buf, line_forward);
|
||||||
|
itoa(columns, buf+2);
|
||||||
|
tty_puts(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void left(el_status_t Change)
|
static void left(el_status_t Change)
|
||||||
{
|
{
|
||||||
if (rl_point) {
|
if (rl_point) {
|
||||||
tty_back();
|
if ((rl_point + prompt_len) % tty_cols == 0) {
|
||||||
if (ISMETA(rl_line_buffer[rl_point - 1])) {
|
tty_puts(line_up);
|
||||||
if (rl_meta_chars) {
|
move_cursor_forward(tty_cols);
|
||||||
tty_back();
|
} else {
|
||||||
tty_back();
|
tty_back();
|
||||||
}
|
}
|
||||||
} else if (ISCTL(rl_line_buffer[rl_point - 1])) {
|
if (ISMETA(rl_line_buffer[rl_point - 1])) {
|
||||||
|
if (rl_meta_chars) {
|
||||||
|
tty_back();
|
||||||
|
tty_back();
|
||||||
|
}
|
||||||
|
} else if (ISCTL(rl_line_buffer[rl_point - 1])) {
|
||||||
tty_back();
|
tty_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,7 +406,10 @@ static void left(el_status_t Change)
|
|||||||
|
|
||||||
static void right(el_status_t Change)
|
static void right(el_status_t Change)
|
||||||
{
|
{
|
||||||
tty_show(rl_line_buffer[rl_point]);
|
if ((rl_point + prompt_len + 1) % tty_cols == 0)
|
||||||
|
tty_put('\n');
|
||||||
|
else
|
||||||
|
tty_show(rl_line_buffer[rl_point]);
|
||||||
|
|
||||||
if (Change == CSmove)
|
if (Change == CSmove)
|
||||||
rl_point++;
|
rl_point++;
|
||||||
@ -382,23 +450,23 @@ static el_status_t do_forward(el_status_t move)
|
|||||||
do {
|
do {
|
||||||
p = &rl_line_buffer[rl_point];
|
p = &rl_line_buffer[rl_point];
|
||||||
|
|
||||||
/* Skip leading whitespace, like FSF Readline */
|
/* Skip leading whitespace, like FSF Readline */
|
||||||
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
||||||
if (move == CSmove)
|
if (move == CSmove)
|
||||||
right(CSstay);
|
right(CSstay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip to end of word, if inside a word. */
|
/* Skip to end of word, if inside a word. */
|
||||||
for (; rl_point < rl_end && is_alpha_num(p[0]); rl_point++, p++) {
|
for (; rl_point < rl_end && is_alpha_num(p[0]); rl_point++, p++) {
|
||||||
if (move == CSmove)
|
if (move == CSmove)
|
||||||
right(CSstay);
|
right(CSstay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip to next word, or skip leading white space if outside a word. */
|
/* Skip to next word, or skip leading white space if outside a word. */
|
||||||
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
||||||
if (move == CSmove)
|
if (move == CSmove)
|
||||||
right(CSstay);
|
right(CSstay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rl_point == rl_end)
|
if (rl_point == rl_end)
|
||||||
break;
|
break;
|
||||||
@ -424,7 +492,7 @@ static el_status_t do_case(el_case_t type)
|
|||||||
end = rl_end;
|
end = rl_end;
|
||||||
|
|
||||||
for (i = rl_point, p = &rl_line_buffer[i]; rl_point < end; p++) {
|
for (i = rl_point, p = &rl_line_buffer[i]; rl_point < end; p++) {
|
||||||
if ((type == TOupper) || (type == TOcapitalize && rl_point == i)) {
|
if ((type == TOupper) || (type == TOcapitalize && rl_point == i)) {
|
||||||
if (islower(*p))
|
if (islower(*p))
|
||||||
*p = toupper(*p);
|
*p = toupper(*p);
|
||||||
} else if (isupper(*p)) {
|
} else if (isupper(*p)) {
|
||||||
@ -460,33 +528,54 @@ static void ceol(void)
|
|||||||
|
|
||||||
while (rl_point < 0) {
|
while (rl_point < 0) {
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
rl_point++;
|
rl_point++;
|
||||||
extras++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = rl_point, p = &rl_line_buffer[i]; i <= rl_end; i++, p++) {
|
for (i = rl_point, p = &rl_line_buffer[i]; i <= rl_end; i++, p++) {
|
||||||
tty_put(' ');
|
if ((i + prompt_len + 1) % tty_cols == 0){
|
||||||
|
tty_put(' ');
|
||||||
|
tty_put('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tty_put(' ');
|
||||||
if (ISMETA(*p)) {
|
if (ISMETA(*p)) {
|
||||||
if (rl_meta_chars) {
|
if (rl_meta_chars) {
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
extras += 2;
|
extras += 2;
|
||||||
}
|
}
|
||||||
} else if (ISCTL(*p)) {
|
} else if (ISCTL(*p)) {
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
extras++;
|
extras++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i += extras; i > rl_point; i--)
|
for (i += extras; i > rl_point; i--) {
|
||||||
tty_back();
|
if ((i + prompt_len) % tty_cols == 0) {
|
||||||
|
tty_puts(line_up);
|
||||||
|
move_cursor_forward(tty_cols);
|
||||||
|
} else {
|
||||||
|
tty_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_line(void)
|
static void clear_line(void)
|
||||||
{
|
{
|
||||||
|
int n = (rl_point + prompt_len) / tty_cols;
|
||||||
rl_point = -(int)strlen(rl_prompt);
|
rl_point = -(int)strlen(rl_prompt);
|
||||||
tty_put('\r');
|
|
||||||
|
if (n > 0) {
|
||||||
|
for(int k = 0; k < n; k++)
|
||||||
|
tty_puts(line_up);
|
||||||
|
tty_put('\r');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tty_put('\r');
|
||||||
|
}
|
||||||
|
|
||||||
ceol();
|
ceol();
|
||||||
|
|
||||||
rl_point = 0;
|
rl_point = 0;
|
||||||
rl_end = 0;
|
rl_end = 0;
|
||||||
rl_line_buffer[0] = '\0';
|
rl_line_buffer[0] = '\0';
|
||||||
@ -501,7 +590,7 @@ static el_status_t insert_string(const char *p)
|
|||||||
|
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
if (rl_end + len >= Length) {
|
if (rl_end + len >= Length) {
|
||||||
line = malloc(sizeof(char) * (Length + len + MEM_INC));
|
line = malloc(sizeof(char) * (Length + len + MEM_INC));
|
||||||
if (!line)
|
if (!line)
|
||||||
return CSstay;
|
return CSstay;
|
||||||
|
|
||||||
@ -538,14 +627,15 @@ int rl_insert_text(const char *text)
|
|||||||
|
|
||||||
static el_status_t redisplay(int cls)
|
static el_status_t redisplay(int cls)
|
||||||
{
|
{
|
||||||
if (cls && rl_point == 0 && rl_end == 0)
|
if (cls)
|
||||||
tty_puts(CLEAR);
|
tty_puts(CLEAR);
|
||||||
else
|
else
|
||||||
tty_puts("\r\e[K");
|
tty_puts("\r\e[K");
|
||||||
|
|
||||||
tty_puts(rl_prompt);
|
tty_puts(rl_prompt);
|
||||||
|
rl_point = 0;
|
||||||
tty_string(rl_line_buffer);
|
tty_string(rl_line_buffer);
|
||||||
|
rl_point = rl_end;
|
||||||
return CSmove;
|
return CSmove;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +675,7 @@ static el_status_t do_insert_hist(const char *p)
|
|||||||
clear_line();
|
clear_line();
|
||||||
|
|
||||||
rl_point = 0;
|
rl_point = 0;
|
||||||
reposition();
|
reposition(-1);
|
||||||
rl_end = 0;
|
rl_end = 0;
|
||||||
|
|
||||||
return insert_string(p);
|
return insert_string(p);
|
||||||
@ -607,7 +697,7 @@ static el_status_t do_hist(const char *(*move)(void))
|
|||||||
static el_status_t h_next(void)
|
static el_status_t h_next(void)
|
||||||
{
|
{
|
||||||
if (el_no_hist)
|
if (el_no_hist)
|
||||||
return CSstay;
|
return CSstay;
|
||||||
|
|
||||||
return do_hist(el_next_hist);
|
return do_hist(el_next_hist);
|
||||||
}
|
}
|
||||||
@ -615,7 +705,7 @@ static el_status_t h_next(void)
|
|||||||
static el_status_t h_prev(void)
|
static el_status_t h_prev(void)
|
||||||
{
|
{
|
||||||
if (el_no_hist)
|
if (el_no_hist)
|
||||||
return CSstay;
|
return CSstay;
|
||||||
|
|
||||||
return do_hist(el_prev_hist);
|
return do_hist(el_prev_hist);
|
||||||
}
|
}
|
||||||
@ -720,8 +810,8 @@ static el_status_t h_search(void)
|
|||||||
|
|
||||||
search_move = Repeat == NO_ARG ? el_prev_hist : el_next_hist;
|
search_move = Repeat == NO_ARG ? el_prev_hist : el_next_hist;
|
||||||
if (line_handler) {
|
if (line_handler) {
|
||||||
editinput(0);
|
editinput(0);
|
||||||
return CSstay;
|
return CSstay;
|
||||||
}
|
}
|
||||||
|
|
||||||
return h_search_end(editinput(1));
|
return h_search_end(editinput(1));
|
||||||
@ -792,6 +882,7 @@ static el_status_t delete_string(int count)
|
|||||||
for (p = &rl_line_buffer[rl_point], i = rl_end - (rl_point + count) + 1; --i >= 0; p++)
|
for (p = &rl_line_buffer[rl_point], i = rl_end - (rl_point + count) + 1; --i >= 0; p++)
|
||||||
p[0] = p[count];
|
p[0] = p[count];
|
||||||
ceol();
|
ceol();
|
||||||
|
|
||||||
rl_end -= count;
|
rl_end -= count;
|
||||||
tty_string(&rl_line_buffer[rl_point]);
|
tty_string(&rl_line_buffer[rl_point]);
|
||||||
|
|
||||||
@ -832,7 +923,7 @@ static el_status_t kill_line(void)
|
|||||||
if (Repeat < rl_point) {
|
if (Repeat < rl_point) {
|
||||||
i = rl_point;
|
i = rl_point;
|
||||||
rl_point = Repeat;
|
rl_point = Repeat;
|
||||||
reposition();
|
reposition(-1);
|
||||||
delete_string(i - rl_point);
|
delete_string(i - rl_point);
|
||||||
} else if (Repeat > rl_point) {
|
} else if (Repeat > rl_point) {
|
||||||
right(CSmove);
|
right(CSmove);
|
||||||
@ -946,43 +1037,43 @@ static el_status_t meta(void)
|
|||||||
/* Also include VT-100 arrows. */
|
/* Also include VT-100 arrows. */
|
||||||
if (c == '[' || c == 'O') {
|
if (c == '[' || c == 'O') {
|
||||||
switch (tty_get()) {
|
switch (tty_get()) {
|
||||||
case EOF: return CSeof;
|
case EOF: return CSeof;
|
||||||
case '1':
|
case '1':
|
||||||
{
|
{
|
||||||
char seq[4] = { 0 };
|
char seq[4] = { 0 };
|
||||||
|
|
||||||
for (c = 0; c < 3; c++)
|
for (c = 0; c < 3; c++)
|
||||||
seq[c] = tty_get();
|
seq[c] = tty_get();
|
||||||
|
|
||||||
if (!strncmp(seq, ";5C", 3))
|
if (!strncmp(seq, ";5C", 3))
|
||||||
return fd_word(); /* Ctrl+Right */
|
return fd_word(); /* Ctrl+Right */
|
||||||
if (!strncmp(seq, ";5D", 3))
|
if (!strncmp(seq, ";5D", 3))
|
||||||
return bk_word(); /* Ctrl+Left */
|
return bk_word(); /* Ctrl+Left */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '2': tty_get(); return CSstay; /* Insert */
|
case '2': tty_get(); return CSstay; /* Insert */
|
||||||
case '3': tty_get(); return del_char(); /* Delete */
|
case '3': tty_get(); return del_char(); /* Delete */
|
||||||
case '5': tty_get(); return CSstay; /* PgUp */
|
case '5': tty_get(); return CSstay; /* PgUp */
|
||||||
case '6': tty_get(); return CSstay; /* PgDn */
|
case '6': tty_get(); return CSstay; /* PgDn */
|
||||||
case 'A': return h_prev(); /* Up */
|
case 'A': return h_prev(); /* Up */
|
||||||
case 'B': return h_next(); /* Down */
|
case 'B': return h_next(); /* Down */
|
||||||
case 'C': return fd_char(); /* Left */
|
case 'C': return fd_char(); /* Left */
|
||||||
case 'D': return bk_char(); /* Right */
|
case 'D': return bk_char(); /* Right */
|
||||||
case 'F': return end_line(); /* End */
|
case 'F': return end_line(); /* End */
|
||||||
case 'H': return beg_line(); /* Home */
|
case 'H': return beg_line(); /* Home */
|
||||||
default: /* Fall through */
|
default: /* Fall through */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return el_ring_bell();
|
return el_ring_bell();
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ANSI_ARROWS */
|
#endif /* CONFIG_ANSI_ARROWS */
|
||||||
|
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
for (Repeat = c - '0'; (c = tty_get()) != EOF && isdigit(c); )
|
for (Repeat = c - '0'; (c = tty_get()) != EOF && isdigit(c); )
|
||||||
Repeat = Repeat * 10 + c - '0';
|
Repeat = Repeat * 10 + c - '0';
|
||||||
tty_push(c);
|
tty_push(c);
|
||||||
|
|
||||||
return CSstay;
|
return CSstay;
|
||||||
}
|
}
|
||||||
@ -1007,7 +1098,7 @@ static el_status_t emacs(int c)
|
|||||||
old_point = rl_point;
|
old_point = rl_point;
|
||||||
|
|
||||||
if (rl_meta_chars && ISMETA(c)) {
|
if (rl_meta_chars && ISMETA(c)) {
|
||||||
tty_push(UNMETA(c));
|
tty_push(UNMETA(c));
|
||||||
return meta();
|
return meta();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1017,11 +1108,11 @@ static el_status_t emacs(int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kp->Function) {
|
if (kp->Function) {
|
||||||
s = kp->Function();
|
s = kp->Function();
|
||||||
if (s == CSdispatch) /* If Function is inhibited. */
|
if (s == CSdispatch) /* If Function is inhibited. */
|
||||||
s = insert_char(c);
|
s = insert_char(c);
|
||||||
} else {
|
} else {
|
||||||
s = insert_char(c);
|
s = insert_char(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!el_pushed) {
|
if (!el_pushed) {
|
||||||
@ -1059,12 +1150,13 @@ static el_status_t tty_special(int c)
|
|||||||
|
|
||||||
if (c == rl_kill) {
|
if (c == rl_kill) {
|
||||||
if (rl_point != 0) {
|
if (rl_point != 0) {
|
||||||
|
old_point = rl_point;
|
||||||
rl_point = 0;
|
rl_point = 0;
|
||||||
reposition();
|
reposition(c);
|
||||||
}
|
}
|
||||||
Repeat = NO_ARG;
|
Repeat = NO_ARG;
|
||||||
|
|
||||||
return kill_line();
|
return kill_line();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EOF
|
#ifdef CONFIG_EOF
|
||||||
@ -1080,47 +1172,47 @@ static char *editinput(int complete)
|
|||||||
int c;
|
int c;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
c = tty_get();
|
c = tty_get();
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (tty_special(c)) {
|
switch (tty_special(c)) {
|
||||||
case CSdone:
|
case CSdone:
|
||||||
return rl_line_buffer;
|
return rl_line_buffer;
|
||||||
|
|
||||||
case CSeof:
|
case CSeof:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case CSsignal:
|
case CSsignal:
|
||||||
return (char *)"";
|
return (char *)"";
|
||||||
|
|
||||||
case CSmove:
|
case CSmove:
|
||||||
reposition();
|
reposition(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CSdispatch:
|
case CSdispatch:
|
||||||
switch (emacs(c)) {
|
switch (emacs(c)) {
|
||||||
case CSdone:
|
case CSdone:
|
||||||
return rl_line_buffer;
|
return rl_line_buffer;
|
||||||
|
|
||||||
case CSeof:
|
case CSeof:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case CSsignal:
|
case CSsignal:
|
||||||
return (char *)"";
|
return (char *)"";
|
||||||
|
|
||||||
case CSmove:
|
case CSmove:
|
||||||
reposition();
|
reposition(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CSdispatch:
|
case CSdispatch:
|
||||||
case CSstay:
|
case CSstay:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CSstay:
|
case CSstay:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (complete);
|
} while (complete);
|
||||||
|
|
||||||
@ -1130,7 +1222,7 @@ static char *editinput(int complete)
|
|||||||
static void hist_alloc(void)
|
static void hist_alloc(void)
|
||||||
{
|
{
|
||||||
if (!H.Lines)
|
if (!H.Lines)
|
||||||
H.Lines = calloc(el_hist_size, sizeof(char *));
|
H.Lines = calloc(el_hist_size, sizeof(char *));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hist_add(const char *p)
|
static void hist_add(const char *p)
|
||||||
@ -1167,7 +1259,7 @@ static char *read_redirected(void)
|
|||||||
|
|
||||||
p = line = malloc(sizeof(char) * size);
|
p = line = malloc(sizeof(char) * size);
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
end = p + size;
|
end = p + size;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -1176,8 +1268,8 @@ static char *read_redirected(void)
|
|||||||
|
|
||||||
size += MEM_INC;
|
size += MEM_INC;
|
||||||
p = line = realloc(line, sizeof(char) * size);
|
p = line = realloc(line, sizeof(char) * size);
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
end = p + size;
|
end = p + size;
|
||||||
|
|
||||||
p += oldpos; /* Continue where we left off... */
|
p += oldpos; /* Continue where we left off... */
|
||||||
@ -1189,7 +1281,7 @@ static char *read_redirected(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p == '\n')
|
if (*p == '\n')
|
||||||
break;
|
break;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
@ -1221,31 +1313,31 @@ void rl_reset_terminal(const char *terminal_name)
|
|||||||
#ifdef CONFIG_USE_TERMCAP
|
#ifdef CONFIG_USE_TERMCAP
|
||||||
bp = buf;
|
bp = buf;
|
||||||
if (-1 != tgetent(buf, el_term)) {
|
if (-1 != tgetent(buf, el_term)) {
|
||||||
if ((backspace = tgetstr("le", &bp)) != NULL)
|
if ((backspace = tgetstr("le", &bp)) != NULL)
|
||||||
backspace = strdup(backspace);
|
backspace = strdup(backspace);
|
||||||
tty_cols = tgetnum("co");
|
tty_cols = tgetnum("co");
|
||||||
tty_rows = tgetnum("li");
|
tty_rows = tgetnum("li");
|
||||||
}
|
}
|
||||||
/* Make sure to check width & rows and fallback to TIOCGWINSZ if available. */
|
/* Make sure to check width & rows and fallback to TIOCGWINSZ if available. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tty_cols <= 0 || tty_rows <= 0) {
|
if (tty_cols <= 0 || tty_rows <= 0) {
|
||||||
#ifdef TIOCGWINSZ
|
#ifdef TIOCGWINSZ
|
||||||
if (ioctl(el_outfd, TIOCGWINSZ, &W) >= 0 && W.ws_col > 0 && W.ws_row > 0) {
|
if (ioctl(el_outfd, TIOCGWINSZ, &W) >= 0 && W.ws_col > 0 && W.ws_row > 0) {
|
||||||
tty_cols = (int)W.ws_col;
|
tty_cols = (int)W.ws_col;
|
||||||
tty_rows = (int)W.ws_row;
|
tty_rows = (int)W.ws_row;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tty_cols = SCREEN_COLS;
|
tty_cols = SCREEN_COLS;
|
||||||
tty_rows = SCREEN_ROWS;
|
tty_rows = SCREEN_ROWS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rl_initialize(void)
|
void rl_initialize(void)
|
||||||
{
|
{
|
||||||
if (!rl_prompt)
|
if (!rl_prompt)
|
||||||
rl_prompt = "? ";
|
rl_prompt = "? ";
|
||||||
|
|
||||||
hist_alloc();
|
hist_alloc();
|
||||||
|
|
||||||
@ -1264,24 +1356,24 @@ void rl_uninitialize(void)
|
|||||||
|
|
||||||
/* Uninitialize the history */
|
/* Uninitialize the history */
|
||||||
if (H.Lines) {
|
if (H.Lines) {
|
||||||
for (i = 0; i < el_hist_size; i++) {
|
for (i = 0; i < el_hist_size; i++) {
|
||||||
if (H.Lines[i])
|
if (H.Lines[i])
|
||||||
free(H.Lines[i]);
|
free(H.Lines[i]);
|
||||||
H.Lines[i] = NULL;
|
H.Lines[i] = NULL;
|
||||||
}
|
}
|
||||||
free(H.Lines);
|
free(H.Lines);
|
||||||
H.Lines = NULL;
|
H.Lines = NULL;
|
||||||
}
|
}
|
||||||
H.Size = 0;
|
H.Size = 0;
|
||||||
H.Pos = 0;
|
H.Pos = 0;
|
||||||
|
|
||||||
if (old_search)
|
if (old_search)
|
||||||
free(old_search);
|
free(old_search);
|
||||||
old_search = NULL;
|
old_search = NULL;
|
||||||
|
|
||||||
/* Uninitialize the line buffer */
|
/* Uninitialize the line buffer */
|
||||||
if (rl_line_buffer)
|
if (rl_line_buffer)
|
||||||
free(rl_line_buffer);
|
free(rl_line_buffer);
|
||||||
rl_line_buffer = NULL;
|
rl_line_buffer = NULL;
|
||||||
Length = 0;
|
Length = 0;
|
||||||
}
|
}
|
||||||
@ -1295,7 +1387,7 @@ void rl_save_prompt(void)
|
|||||||
void rl_restore_prompt(void)
|
void rl_restore_prompt(void)
|
||||||
{
|
{
|
||||||
if (rl_saved_prompt)
|
if (rl_saved_prompt)
|
||||||
rl_prompt = rl_saved_prompt;
|
rl_prompt = rl_saved_prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rl_set_prompt(const char *prompt)
|
void rl_set_prompt(const char *prompt)
|
||||||
@ -1320,9 +1412,9 @@ static int el_prep(const char *prompt)
|
|||||||
|
|
||||||
if (!rl_line_buffer) {
|
if (!rl_line_buffer) {
|
||||||
Length = MEM_INC;
|
Length = MEM_INC;
|
||||||
rl_line_buffer = malloc(sizeof(char) * Length);
|
rl_line_buffer = malloc(sizeof(char) * Length);
|
||||||
if (!rl_line_buffer)
|
if (!rl_line_buffer)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_info();
|
tty_info();
|
||||||
@ -1331,18 +1423,20 @@ static int el_prep(const char *prompt)
|
|||||||
ScreenSize = SCREEN_INC;
|
ScreenSize = SCREEN_INC;
|
||||||
Screen = malloc(sizeof(char) * ScreenSize);
|
Screen = malloc(sizeof(char) * ScreenSize);
|
||||||
if (!Screen)
|
if (!Screen)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rl_prompt = prompt ? prompt : NILSTR;
|
rl_prompt = prompt ? prompt : NILSTR;
|
||||||
if (el_no_echo) {
|
prompt_len = strlen(rl_prompt);
|
||||||
int old = el_no_echo;
|
|
||||||
|
|
||||||
el_no_echo = 0;
|
if (el_no_echo) {
|
||||||
tty_puts(rl_prompt);
|
int old = el_no_echo;
|
||||||
tty_flush();
|
|
||||||
el_no_echo = old;
|
el_no_echo = 0;
|
||||||
|
tty_puts(rl_prompt);
|
||||||
|
tty_flush();
|
||||||
|
el_no_echo = old;
|
||||||
} else {
|
} else {
|
||||||
tty_puts(rl_prompt);
|
tty_puts(rl_prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeat = NO_ARG;
|
Repeat = NO_ARG;
|
||||||
@ -1363,8 +1457,8 @@ static char *el_deprep(char *line)
|
|||||||
|
|
||||||
rl_deprep_term_function();
|
rl_deprep_term_function();
|
||||||
if (Screen) {
|
if (Screen) {
|
||||||
free(Screen);
|
free(Screen);
|
||||||
Screen = NULL;
|
Screen = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(H.Lines[--H.Size]);
|
free(H.Lines[--H.Size]);
|
||||||
@ -1372,14 +1466,14 @@ static char *el_deprep(char *line)
|
|||||||
|
|
||||||
/* Add to history, unless no-echo or no-history mode ... */
|
/* Add to history, unless no-echo or no-history mode ... */
|
||||||
if (!el_no_echo && !el_no_hist) {
|
if (!el_no_echo && !el_no_hist) {
|
||||||
if (line != NULL && *line != '\0')
|
if (line != NULL && *line != '\0')
|
||||||
hist_add(line);
|
hist_add(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (el_intr_pending > 0) {
|
if (el_intr_pending > 0) {
|
||||||
int signo = el_intr_pending;
|
int signo = el_intr_pending;
|
||||||
|
|
||||||
el_intr_pending = 0;
|
el_intr_pending = 0;
|
||||||
kill(getpid(), signo);
|
kill(getpid(), signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,7 +1483,7 @@ static char *el_deprep(char *line)
|
|||||||
void rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *lhandler)
|
void rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *lhandler)
|
||||||
{
|
{
|
||||||
if (!lhandler)
|
if (!lhandler)
|
||||||
return;
|
return;
|
||||||
line_handler = lhandler;
|
line_handler = lhandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1417,8 +1511,8 @@ void rl_callback_read_char(void)
|
|||||||
char *line;
|
char *line;
|
||||||
|
|
||||||
if (!line_handler) {
|
if (!line_handler) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1426,26 +1520,26 @@ void rl_callback_read_char(void)
|
|||||||
* This is the only point where we can tell user
|
* This is the only point where we can tell user
|
||||||
*/
|
*/
|
||||||
if (!Screen || !rl_line_buffer) {
|
if (!Screen || !rl_line_buffer) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
line_handler(el_deprep(NULL));
|
line_handler(el_deprep(NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = editinput(0);
|
line = editinput(0);
|
||||||
if (line) {
|
if (line) {
|
||||||
char *l;
|
char *l;
|
||||||
|
|
||||||
if (Searching) {
|
if (Searching) {
|
||||||
h_search_end(line);
|
h_search_end(line);
|
||||||
tty_flush();
|
tty_flush();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = el_deprep(line);
|
l = el_deprep(line);
|
||||||
line_handler(l);
|
line_handler(l);
|
||||||
|
|
||||||
if (el_prep(rl_prompt))
|
if (el_prep(rl_prompt))
|
||||||
line_handler(NULL);
|
line_handler(NULL);
|
||||||
}
|
}
|
||||||
tty_flush();
|
tty_flush();
|
||||||
}
|
}
|
||||||
@ -1453,7 +1547,7 @@ void rl_callback_read_char(void)
|
|||||||
void rl_callback_handler_remove(void)
|
void rl_callback_handler_remove(void)
|
||||||
{
|
{
|
||||||
if (!line_handler)
|
if (!line_handler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
el_deprep(NULL);
|
el_deprep(NULL);
|
||||||
line_handler = NULL;
|
line_handler = NULL;
|
||||||
@ -1471,7 +1565,7 @@ char *readline(const char *prompt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (el_prep(prompt))
|
if (el_prep(prompt))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return el_deprep(editinput(1));
|
return el_deprep(editinput(1));
|
||||||
}
|
}
|
||||||
@ -1497,16 +1591,16 @@ int read_history(const char *filename)
|
|||||||
hist_alloc();
|
hist_alloc();
|
||||||
fp = fopen(filename, "r");
|
fp = fopen(filename, "r");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
H.Size = 0;
|
H.Size = 0;
|
||||||
while (H.Size < el_hist_size) {
|
while (H.Size < el_hist_size) {
|
||||||
if (!fgets(buf, SCREEN_INC, fp))
|
if (!fgets(buf, SCREEN_INC, fp))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buf[strlen(buf) - 1] = 0; /* Remove '\n' */
|
buf[strlen(buf) - 1] = 0; /* Remove '\n' */
|
||||||
add_history(buf);
|
add_history(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fclose(fp);
|
return fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return errno;
|
return errno;
|
||||||
@ -1519,12 +1613,12 @@ int write_history(const char *filename)
|
|||||||
hist_alloc();
|
hist_alloc();
|
||||||
fp = fopen(filename, "w");
|
fp = fopen(filename, "w");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (i < H.Size)
|
while (i < H.Size)
|
||||||
fprintf(fp, "%s\n", H.Lines[i++]);
|
fprintf(fp, "%s\n", H.Lines[i++]);
|
||||||
|
|
||||||
return fclose(fp);
|
return fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return errno;
|
return errno;
|
||||||
@ -1563,7 +1657,7 @@ char *el_find_word(void)
|
|||||||
while (p < &rl_line_buffer[rl_point]) {
|
while (p < &rl_line_buffer[rl_point]) {
|
||||||
if (*p == '\\') {
|
if (*p == '\\') {
|
||||||
if (++p == &rl_line_buffer[rl_point])
|
if (++p == &rl_line_buffer[rl_point])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*q++ = *p++;
|
*q++ = *p++;
|
||||||
}
|
}
|
||||||
@ -1603,7 +1697,7 @@ static el_status_t c_complete(void)
|
|||||||
el_status_t s = CSdone;
|
el_status_t s = CSdone;
|
||||||
|
|
||||||
if (rl_inhibit_complete)
|
if (rl_inhibit_complete)
|
||||||
return CSdispatch;
|
return CSdispatch;
|
||||||
|
|
||||||
word = el_find_word();
|
word = el_find_word();
|
||||||
p = rl_complete(word, &unique);
|
p = rl_complete(word, &unique);
|
||||||
@ -1614,14 +1708,14 @@ static el_status_t c_complete(void)
|
|||||||
word = p;
|
word = p;
|
||||||
|
|
||||||
string = q = malloc(sizeof(char) * (2 * len + 1));
|
string = q = malloc(sizeof(char) * (2 * len + 1));
|
||||||
if (!string) {
|
if (!string) {
|
||||||
free(word);
|
free(word);
|
||||||
return CSstay;
|
return CSstay;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if ((*p < ' ' || strchr(SEPS, *p) != NULL)
|
if ((*p < ' ' || strchr(SEPS, *p) != NULL)
|
||||||
&& (!unique || p[1] != 0)) {
|
&& (!unique || p[1] != 0)) {
|
||||||
*q++ = '\\';
|
*q++ = '\\';
|
||||||
}
|
}
|
||||||
*q++ = *p++;
|
*q++ = *p++;
|
||||||
@ -1639,7 +1733,7 @@ static el_status_t c_complete(void)
|
|||||||
free(string);
|
free(string);
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return c_possible();
|
return c_possible();
|
||||||
@ -1779,7 +1873,7 @@ static int argify(char *line, char ***avp)
|
|||||||
i = MEM_INC;
|
i = MEM_INC;
|
||||||
*avp = p = malloc(sizeof(char *) * i);
|
*avp = p = malloc(sizeof(char *) * i);
|
||||||
if (!p)
|
if (!p)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (c = line; isspace(*c); c++)
|
for (c = line; isspace(*c); c++)
|
||||||
continue;
|
continue;
|
||||||
@ -1789,26 +1883,26 @@ static int argify(char *line, char ***avp)
|
|||||||
|
|
||||||
for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
|
for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
|
||||||
if (!isspace(*c)) {
|
if (!isspace(*c)) {
|
||||||
c++;
|
c++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*c++ = '\0';
|
*c++ = '\0';
|
||||||
if (*c && *c != '\n') {
|
if (*c && *c != '\n') {
|
||||||
if (ac + 1 == i) {
|
if (ac + 1 == i) {
|
||||||
arg = malloc(sizeof(char *) * (i + MEM_INC));
|
arg = malloc(sizeof(char *) * (i + MEM_INC));
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
p[ac] = NULL;
|
p[ac] = NULL;
|
||||||
return ac;
|
return ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(arg, p, i * sizeof(char *));
|
memcpy(arg, p, i * sizeof(char *));
|
||||||
i += MEM_INC;
|
i += MEM_INC;
|
||||||
free(p);
|
free(p);
|
||||||
*avp = p = arg;
|
*avp = p = arg;
|
||||||
}
|
}
|
||||||
p[ac++] = c;
|
p[ac++] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
@ -1907,12 +2001,12 @@ static size_t find_key_in_map(int key, el_keymap_t map[], size_t mapsz)
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; map[i].Function && i < mapsz; i++) {
|
for (i = 0; map[i].Function && i < mapsz; i++) {
|
||||||
if (map[i].Key == key)
|
if (map[i].Key == key)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < mapsz)
|
if (i < mapsz)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
return mapsz;
|
return mapsz;
|
||||||
}
|
}
|
||||||
@ -1924,8 +2018,8 @@ static el_status_t el_bind_key_in_map(int key, el_keymap_func_t function, el_key
|
|||||||
/* Must check that pos is not the next to last array position,
|
/* Must check that pos is not the next to last array position,
|
||||||
* otherwise we will write out-of-bounds to terminate the list. */
|
* otherwise we will write out-of-bounds to terminate the list. */
|
||||||
if (pos + 1 >= mapsz) {
|
if (pos + 1 >= mapsz) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return CSeof;
|
return CSeof;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add at end, create new? */
|
/* Add at end, create new? */
|
||||||
@ -1937,8 +2031,8 @@ static el_status_t el_bind_key_in_map(int key, el_keymap_func_t function, el_key
|
|||||||
|
|
||||||
/* Terminate list */
|
/* Terminate list */
|
||||||
if (creat) {
|
if (creat) {
|
||||||
map[pos + 1].Key = 0;
|
map[pos + 1].Key = 0;
|
||||||
map[pos + 1].Function = NULL;
|
map[pos + 1].Function = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CSdone;
|
return CSdone;
|
||||||
|
Loading…
Reference in New Issue
Block a user