diff --git a/include/editline.h b/include/editline.h index eb1a569..15631c6 100644 --- a/include/editline.h +++ b/include/editline.h @@ -90,6 +90,12 @@ extern int el_no_echo; /* E.g under emacs, don't echo except prompt */ extern int el_no_hist; /* Disable auto-save of and access to history -- e.g. for password prompts or wizards */ extern int el_hist_size; /* size of history scrollback buffer, default: 15 */ +extern int el_ret_signals; /* Set this to non-zero to enable use of following constants. Disabled by default. + The constants can be returned by readline(), or be used as callback_handler's parameter. + The caller can not free the constants. */ +extern const char* const el_ret_sigint; /* If got SIGINT from tty, readline will return this if el_ret_signals is non zero */ +extern const char* const el_ret_sigtstp; /* If got SIGTSTP from tty, readline will return this if el_ret_signals is non zero */ + extern void rl_initialize (void); extern void rl_reset_terminal (const char *terminal_name); extern void rl_uninitialize (void); diff --git a/src/editline.c b/src/editline.c index 1d0cfa6..d69e5d6 100644 --- a/src/editline.c +++ b/src/editline.c @@ -114,6 +114,10 @@ static const char *(*search_move)(void); static const char *old_prompt = NULL; static rl_vcpfunc_t *line_handler = NULL; +int el_ret_signals = 0; /* return an empty string by default when got a signal */ +const char* const el_ret_sigint = "^C"; +const char* const el_ret_sigtstp = "^Z"; + int el_no_echo = 0; /* e.g., under Emacs */ int el_no_hist = 0; int rl_point; @@ -686,7 +690,9 @@ static el_status_t h_search_end(const char *p) rl_prompt = old_prompt; Searching = 0; - if (p == NULL && el_intr_pending > 0) { + /* When got a signal, editinput() will either return an empty string, or NULL, or a constant, + none of them makes sense to search with. And we always need to clear el_intr_pending. */ + if (el_intr_pending > 0) { el_intr_pending = 0; clear_line(); return redisplay(); @@ -1069,6 +1075,23 @@ static el_status_t tty_special(int c) return CSdispatch; } +static int is_signal(char* line) +{ + return (line == el_ret_sigint || line == el_ret_sigtstp); +} + +static char* get_signal_str() +{ + if (el_ret_signals) + { + if (el_intr_pending == SIGINT) + return el_ret_sigint; + if (el_intr_pending == SIGTSTP) + return el_ret_sigtstp; + } + return (char *)""; +} + static char *editinput(int complete) { int c; @@ -1086,7 +1109,7 @@ static char *editinput(int complete) return NULL; case CSsignal: - return (char *)""; + return get_signal_str(); case CSmove: reposition(); @@ -1101,7 +1124,7 @@ static char *editinput(int complete) return NULL; case CSsignal: - return (char *)""; + return get_signal_str(); case CSmove: reposition(); @@ -1350,7 +1373,8 @@ static int el_prep(const char *prompt) static char *el_deprep(char *line) { if (line) { - line = strdup(line); + if (!is_signal(line)) + line = strdup(line); tty_puts(NEWLINE); tty_flush(); } @@ -1366,7 +1390,7 @@ static char *el_deprep(char *line) /* Add to history, unless no-echo or no-history mode ... */ if (!el_no_echo && !el_no_hist) { - if (line != NULL && *line != '\0') + if (line != NULL && *line != '\0' && !is_signal(line)) hist_add(line); } @@ -1436,7 +1460,8 @@ void rl_callback_read_char(void) } l = el_deprep(line); - line_handler(l); + line_handler(l); /* l can be el_ret_sigint or el_ret_sigtstp, + in this case the callback function can not free it */ if (el_prep(rl_prompt)) line_handler(NULL);