--- src/readline.c.orig 2006-08-29 12:18:07.000000000 -0700 +++ src/readline.c 2007-07-20 13:35:09.000000000 -0700 @@ -88,6 +88,7 @@ /* readline compatibility stuff - look at readline sources/documentation */ /* to see what these variables mean */ const char *rl_library_version = "EditLine wrapper"; +int rl_readline_version = RL_READLINE_VERSION; static char empty[] = { '\0' }; static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', @@ -131,6 +132,7 @@ VFunction *rl_completion_display_matches_hook = NULL; VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; +KEYMAP_ENTRY_ARRAY emacs_meta_keymap; /* * The current prompt string. @@ -226,6 +228,22 @@ return 1; } +static const char _dothistory[] = "/.history"; + +static const char * +_default_history_file(void) +{ + struct passwd *p; + static char path[PATH_MAX]; + + if (*path) + return path; + if ((p = getpwuid(getuid())) == NULL) + return NULL; + strlcpy(path, p->pw_dir, PATH_MAX); + strlcat(path, _dothistory, PATH_MAX); + return path; +} /* * READLINE compatibility stuff @@ -1117,6 +1135,139 @@ return (max_input_history != INT_MAX); } +static const char _history_tmp_template[] = "/tmp/.historyXXXXXX"; + +int +history_truncate_file (const char *filename, int nlines) +{ + int ret = 0; + FILE *fp, *tp; + char template[sizeof(_history_tmp_template)]; + char buf[4096]; + + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + if ((fp = fopen(filename, "r+")) == NULL) + return errno; + do { + int fd; + + strcpy(template, _history_tmp_template); + if ((fd = mkstemp(template)) < 0) { + ret = errno; + break; + } + do { + char *cp; + + if ((tp = fdopen(fd, "r+")) == NULL) { + close(fd); + ret = errno; + break; + } + do { + off_t off; + int count = 0, left = 0; + + for(;;) { + if (fread(buf, sizeof(buf), 1, fp) != 1) { + if (ferror(fp)) { + ret = errno; + break; + } + if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) { + ret = errno; + break; + } + left = fread(buf, 1, sizeof(buf), fp); + if (ferror(fp)) { + ret = errno; + break; + } + if (left == 0) { + count--; + left = sizeof(buf); + } else if (fwrite(buf, left, 1, tp) != 1) { + ret = errno; + break; + } + fflush(tp); + break; + } + if (fwrite(buf, sizeof(buf), 1, tp) != 1) { + ret = errno; + break; + } + count++; + } + if (ret) + break; + cp = buf + left - 1; + if(*cp != '\n') + cp++; + for(;;) { + while (--cp >= buf) { + if (*cp == '\n') { + if (--nlines == 0) { + if (++cp >= buf + sizeof(buf)) { + count++; + cp = buf; + } + break; + } + } + } + if (nlines <= 0 || count == 0) + break; + count--; + if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) { + ret = errno; + break; + } + if (fread(buf, sizeof(buf), 1, tp) != 1) { + if (ferror(tp)) { + ret = errno; + break; + } + ret = EAGAIN; + break; + } + cp = buf + sizeof(buf); + } + if (ret || nlines > 0) + break; + if (fseeko(fp, 0, SEEK_SET) < 0) { + ret = errno; + break; + } + if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) < 0) { + ret = errno; + break; + } + for(;;) { + if ((left = fread(buf, 1, sizeof(buf), tp)) == 0) { + if (ferror(fp)) + ret = errno; + break; + } + if (fwrite(buf, left, 1, fp) != 1) { + ret = errno; + break; + } + } + fflush(fp); + if((off = ftello(fp)) > 0) + ftruncate(fileno(fp), off); + } while(0); + fclose(tp); + } while(0); + unlink(template); + } while(0); + fclose(fp); + + return ret; +} + /* * read history from a file given @@ -1128,7 +1279,9 @@ if (h == NULL || e == NULL) rl_initialize(); - return (history(h, &ev, H_LOAD, filename) == -1); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + return (history(h, &ev, H_LOAD, filename) == -1 ? (errno ? errno : EINVAL) : 0); } @@ -1142,7 +1295,9 @@ if (h == NULL || e == NULL) rl_initialize(); - return (history(h, &ev, H_SAVE, filename) == -1); + if (filename == NULL && (filename = _default_history_file()) == NULL) + return errno; + return (history(h, &ev, H_SAVE, filename) == -1 ? (errno ? errno : EINVAL) : 0); } @@ -1166,16 +1321,15 @@ return (NULL); curr_num = ev.num; - /* start from most recent */ - if (history(h, &ev, H_FIRST) != 0) + /* start from the oldest */ + if (history(h, &ev, H_LAST) != 0) return (NULL); /* error */ - /* look backwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVENT, num)) + /* look forwards for event matching specified offset */ + if (history(h, &ev, H_NEXT_EVDATA, num, &she.data)) return (NULL); she.line = ev.str; - she.data = NULL; /* restore pointer to where it was */ (void)history(h, &ev, H_SET, curr_num); @@ -1209,19 +1363,66 @@ HIST_ENTRY * remove_history(int num) { - static HIST_ENTRY she; + HIST_ENTRY *he; HistEvent ev; + if ((he = (HIST_ENTRY *)malloc(sizeof(HIST_ENTRY))) == NULL) + return NULL; + if (h == NULL || e == NULL) rl_initialize(); - if (history(h, &ev, H_DEL, num) != 0) + if (history(h, &ev, H_DELDATA, num, &he->data) != 0) { + free(he); return NULL; + } - she.line = ev.str; - she.data = NULL; + he->line = ev.str; + if (history(h, &ev, H_GETSIZE) == 0) + history_length = ev.num; - return &she; + return he; +} + + +/* + * replace the line and data of the num-th entry + */ +HIST_ENTRY * +replace_history_entry(int num, const char *line, histdata_t data) +{ + HIST_ENTRY *he; + HistEvent ev; + int curr_num; + + if (h == NULL || e == NULL) + rl_initialize(); + + /* save current position */ + if (history(h, &ev, H_CURR) != 0) + return (NULL); + curr_num = ev.num; + + /* start from the oldest */ + if (history(h, &ev, H_LAST) != 0) + return (NULL); /* error */ + + if ((he = (HIST_ENTRY *)malloc(sizeof(HIST_ENTRY))) == NULL) + return NULL; + + /* look forwards for event matching specified offset */ + if (history(h, &ev, H_NEXT_EVDATA, num, &he->data)) { + free(he); + return (NULL); + } + + he->line = strdup(ev.str); + history(h, &ev, H_REPLACE, line, data); + + /* restore pointer to where it was */ + (void)history(h, &ev, H_SET, curr_num); + + return (he); } @@ -1234,6 +1435,7 @@ HistEvent ev; history(h, &ev, H_CLEAR); + history_length = 0; } @@ -1305,13 +1507,17 @@ HistEvent ev; int curr_num; - if (pos > history_length || pos < 0) + if (pos >= history_length || pos < 0) return (-1); history(h, &ev, H_CURR); curr_num = ev.num; - if (history(h, &ev, H_SET, pos)) { + /* + * use H_DELDATA to set to nth history (without delete) by passing + * (void **)-1 + */ + if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { history(h, &ev, H_SET, curr_num); return(-1); } @@ -1541,7 +1747,7 @@ * bind key c to readline-type function func */ int -rl_bind_key(int c, int func(int, int)) +rl_bind_key(int c, rl_command_func_t *func) { int retval = -1; @@ -1608,6 +1814,20 @@ return (0); } +int +rl_insert_text(const char *text) +{ + if (!text || *text == 0) + return (0); + + if (h == NULL || e == NULL) + rl_initialize(); + + if (el_insertstr(e, text) < 0) + return (0); + return (strlen(text)); +} + /*ARGSUSED*/ int rl_newline(int count, int c) @@ -1671,7 +1891,7 @@ } else wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); - el_set(e, EL_UNBUFFERED, 1); + //el_set(e, EL_UNBUFFERED, 1); } } @@ -1817,3 +2037,32 @@ rl_point = li->cursor - li->buffer; rl_end = li->lastchar - li->buffer; } + +HISTORY_STATE * +history_get_history_state(void) +{ + HISTORY_STATE *hs; + HistEvent ev; + + if ((hs = malloc(sizeof(HISTORY_STATE))) == NULL) + return (NULL); + hs->length = history_length; + return (hs); +} + +/* unsupported, but needed by python */ +void +rl_cleanup_after_signal(void) +{ +} + +void +rl_free_line_state(void) +{ +} + +int +rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map) +{ + return -1; +}