From 0a75b182b1ce78d29495d55034f88b5cae7ca3b2 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Thu, 5 Aug 2010 01:08:30 +0200 Subject: [PATCH] Improve GNU readline compat, patch by Steve Tell in 1997 and 1998 This changeset adds support for: * rl_prep_terminal(), * rl_deprep_terminal(), both of which are only wrappers to rl_ttyset(). * rl_getc() and: * (*rl_getc_function), defaults to rl_getc() * (*rl_event_hook) * (*rl_prep_term_function), defaults to rl_prep_terminal() * (*rl_deprep_term_function), defaults to rl_deprep_terminal() For further details, see http://www.cs.unc.edu/~tell/dist/magic-readline.README Differences from Steve's commit include: signal safety in rl_getc(), restart read() on EINTR, and make sure to support "int meta_flag" to rl_prep_terminal() which is the GNU syntax. To that end I reused the inverse of rl_meta_chars. --- include/editline.h | 16 ++++++++++++---- src/editline.c | 45 +++++++++++++++++++++++++++++++++++---------- src/sysunix.c | 20 +++++++++++++++----- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/include/editline.h b/include/editline.h index f85bd99..4cd9d04 100644 --- a/include/editline.h +++ b/include/editline.h @@ -30,14 +30,14 @@ typedef enum { typedef char* (*rl_complete_func_t)(char*, int*); typedef int (*rl_list_possib_func_t)(char*, char***); typedef el_status_t (*el_keymap_func_t)(void); +typedef int (*rl_hook_func_t) (void); +typedef int (*rl_getc_func_t)(void); +typedef void (*rl_voidfunc_t)(void); +typedef void (*rl_vintfunc_t)(int); /* Display 8-bit chars "as-is" or as `M-x'? Toggle with M-m. (Default:0 - "as-is") */ extern int rl_meta_chars; -/* Use these functions to set custom command/file completion, see cli.c for example usage. */ -rl_complete_func_t rl_set_complete_func(rl_complete_func_t func); -rl_list_possib_func_t rl_set_list_possib_func(rl_list_possib_func_t func); - /* Editline specific functions. */ void el_bind_key_in_metamap(char c, el_keymap_func_t func); @@ -59,4 +59,12 @@ extern void add_history(const char *line); extern int read_history(const char *filename); extern int write_history(const char *filename); +rl_complete_func_t rl_set_complete_func(rl_complete_func_t func); +rl_list_possib_func_t rl_set_list_possib_func(rl_list_possib_func_t func); + +void rl_prep_terminal(int meta_flag); +void rl_deprep_terminal(void); + +int rl_getc(void); + #endif /* __EDITLINE_H__ */ diff --git a/src/editline.c b/src/editline.c index f95a2b6..17dc553 100644 --- a/src/editline.c +++ b/src/editline.c @@ -63,6 +63,11 @@ typedef struct { char **Lines; } el_hist_t; +rl_getc_func_t rl_getc_function = rl_getc; +rl_hook_func_t rl_event_hook; +rl_vintfunc_t rl_prep_term_function = rl_prep_terminal; +rl_voidfunc_t rl_deprep_term_function = rl_deprep_terminal; + /* ** Globals. */ @@ -109,6 +114,7 @@ int rl_meta_chars = 0; /* Display 8-bit chars as the actual char(0 char *rl_line_buffer; const char *rl_prompt; const char *rl_readline_name;/* Set by calling program, for conditional parsing of ~/.inputrc - Not supported yet! */ +FILE *rl_instream; /* User definable callbacks. */ char **(*rl_attempted_completion_function)(const char *token, int start, int end); @@ -196,11 +202,20 @@ static void tty_push(int c) el_push_back = c; } +int rl_getc(void) +{ + int r; + char c; + + do { + r = read(0, &c, 1); + } while (r == -1 && errno == EINTR); + + return r == 1 ? c : EOF; +} + static int tty_get(void) { - char c; - int r; - tty_flush(); if (el_pushed) { el_pushed = 0; @@ -208,12 +223,8 @@ static int tty_get(void) } if (*el_input) return *el_input++; - do - { - r = read(0, &c, 1); - } while (r == -1 && errno == EINTR); - return r == 1 ? c : EOF; + return rl_getc_function(); } #define tty_back() (backspace ? tty_puts(backspace) : tty_put('\b')) @@ -280,6 +291,20 @@ static void tty_info(void) } +/* +** Glue routines to rl_ttyset() +*/ +void rl_prep_terminal(int meta_flag) +{ + rl_meta_chars = !meta_flag; + rl_ttyset(0); +} + +void rl_deprep_terminal(void) +{ + rl_ttyset(1); +} + /* ** Print an array of words in columns. */ @@ -1104,7 +1129,7 @@ char *readline(const char *prompt) } tty_info(); - rl_ttyset(0); + rl_prep_term_function(!rl_meta_chars); hist_add(NILSTR); ScreenSize = SCREEN_INC; Screen = malloc(sizeof(char) * ScreenSize); @@ -1129,7 +1154,7 @@ char *readline(const char *prompt) tty_flush(); } - rl_ttyset(1); + rl_deprep_term_function(); free(Screen); free(H.Lines[--H.Size]); diff --git a/src/sysunix.c b/src/sysunix.c index 4827f33..7d38eb7 100644 --- a/src/sysunix.c +++ b/src/sysunix.c @@ -43,7 +43,11 @@ void rl_ttyset(int Reset) new = old; new.c_lflag &= ~(ECHO | ICANON | ISIG); - new.c_iflag &= ~(ISTRIP | INPCK); + new.c_iflag &= ~INPCK; + if (rl_meta_chars) + new.c_iflag |= ISTRIP; + else + new.c_iflag &= ~ISTRIP; new.c_cc[VMIN] = 1; new.c_cc[VTIME] = 0; if (-1 == tcsetattr(0, TCSADRAIN, &new)) @@ -76,7 +80,12 @@ void rl_ttyset(int Reset) new = old; new.c_lflag &= ~(ECHO | ICANON | ISIG); - new.c_iflag &= ~(ISTRIP | INPCK); + new.c_iflag &= ~INPCK; + if (rl_meta_chars) + new.c_iflag |= ISTRIP; + else + new.c_iflag &= ~ISTRIP; + new.c_cc[VMIN] = 1; new.c_cc[VTIME] = 0; if (-1 == ioctl(0, TCSETAW, &new)) @@ -121,9 +130,10 @@ void rl_ttyset(int Reset) new_sgttyb = old_sgttyb; new_sgttyb.sg_flags &= ~ECHO; new_sgttyb.sg_flags |= RAW; -#ifdef PASS8 - new_sgttyb.sg_flags |= PASS8; -#endif + if (rl_meta_chars) + new_sgttyb.sg_flags &= ~PASS8; + else + new_sgttyb.sg_flags |= PASS8; if (-1 == ioctl(0, TIOCSETP, &new_sgttyb)) perror("Failed TIOCSETP"); new_tchars = old_tchars;