diff --git a/librz/cons/cons.c b/librz/cons/cons.c index d6ce0b23948..17d14f7ae88 100644 --- a/librz/cons/cons.c +++ b/librz/cons/cons.c @@ -673,7 +673,7 @@ RZ_API RzCons *rz_cons_free(void) { restore_console_state(); #endif if (I.line) { - rz_line_free(); + rz_line_free(I.line); I.line = NULL; } RZ_FREE(I.input->readbuffer); diff --git a/librz/cons/dietline.c b/librz/cons/dietline.c index d19997ae73c..58f1efba639 100644 --- a/librz/cons/dietline.c +++ b/librz/cons/dietline.c @@ -16,7 +16,7 @@ #include #endif -static char *rz_line_nullstr = ""; +static const char *rz_line_nullstr = ""; static const char word_break_characters[] = "\t\n ~`!@#$%^&*()-_=+[]{}\\|;:\"'<>,./"; typedef enum { @@ -57,41 +57,41 @@ static void undo_entry_free(RzLineUndoEntry *e, void *user) { RZ_FREE(e->inserted_text); } -static bool undo_reset(void) { - if (I.enable_vi_mode || I.hud) { - // Undo functionality does not yet support vi_mode. +static bool undo_reset(RzLine *line) { + if (line->enable_vi_mode || line->hud) { + // FIXME: Undo functionality doesn't support vi_mode yet. return true; } - if (I.undo_vec) { - rz_vector_free(I.undo_vec); + if (line->undo_vec) { + rz_vector_free(line->undo_vec); } - I.undo_cursor = 0; - I.undo_continue = false; - I.undo_vec = rz_vector_new(sizeof(RzLineUndoEntry), (RzVectorFree)undo_entry_free, NULL); - return !!I.undo_vec; + line->undo_cursor = 0; + line->undo_continue = false; + line->undo_vec = rz_vector_new(sizeof(RzLineUndoEntry), (RzVectorFree)undo_entry_free, NULL); + return !!line->undo_vec; } /* If possible, concatenate input characters according to the behavior of bash. (Others such as zsh don't do that) */ -static bool undo_concat_entry(const char *diff, const int diff_len) { - if (!I.undo_vec->len) { +static bool undo_concat_entry(RzLine *line, const char *diff, const int diff_len) { + if (!line->undo_vec->len) { return false; } // undo_vector has one or more entries. - if (I.undo_cursor != I.undo_vec->len) { + if (line->undo_cursor != line->undo_vec->len) { return false; } // cursor is at tail - RzLineUndoEntry *e = rz_vector_tail(I.undo_vec); + RzLineUndoEntry *e = rz_vector_tail(line->undo_vec); if (!is_undo_entry_valid(e)) { // entry broken - undo_reset(); + undo_reset(line); return false; } if (e->deleted_len || !e->inserted_len) { // concat only works for inserted text, not deleted or replaced. return false; } - if (e->offset + e->inserted_len != I.buffer.index) { + if (e->offset + e->inserted_len != line->buffer.index) { return false; } if (e->inserted_len + diff_len > 20) { @@ -101,7 +101,7 @@ static bool undo_concat_entry(const char *diff, const int diff_len) { e->inserted_len += diff_len; if (!e->inserted_text) { // realloc broken - undo_reset(); + undo_reset(line); return false; } return true; @@ -109,20 +109,21 @@ static bool undo_concat_entry(const char *diff, const int diff_len) { /** * \brief Add an entry to undo vector. + * \param line RzLine instance * \param offset The beginning index of buffer edit * \param deleted_text Text to be deleted. need to be allocated beforehand. Either deleted_text or inserted_text should be non-empty. * \param inserted_text Text to be inserted. need to be allocated beforehand. Either deleted_text or inserted_text should be non-empty. * \return true if success and false if failed. when failed, arg texts are freed. * **/ -static bool undo_add_entry(int offset, RZ_OWN char *deleted_text, RZ_OWN char *inserted_text) { - if (I.enable_vi_mode || I.hud) { +static bool undo_add_entry(RzLine *line, int offset, RZ_OWN char *deleted_text, RZ_OWN char *inserted_text) { + if (line->enable_vi_mode || line->hud) { // Undo functionality does not yet support vi_mode. RZ_FREE(deleted_text); RZ_FREE(inserted_text); return false; } - if (!I.undo_vec || I.undo_vec->len > RZ_LINE_UNDOSIZE) { - undo_reset(); + if (!line->undo_vec || line->undo_vec->len > RZ_LINE_UNDOSIZE) { + undo_reset(line); } RzLineUndoEntry new_entry = { offset, @@ -130,7 +131,7 @@ static bool undo_add_entry(int offset, RZ_OWN char *deleted_text, RZ_OWN char *i deleted_text ? rz_str_nlen(deleted_text, RZ_LINE_BUFSIZE) : 0, inserted_text, inserted_text ? rz_str_nlen(inserted_text, RZ_LINE_BUFSIZE) : 0, - I.undo_continue, + line->undo_continue, false }; if (!is_undo_entry_valid(&new_entry)) { @@ -139,54 +140,54 @@ static bool undo_add_entry(int offset, RZ_OWN char *deleted_text, RZ_OWN char *i RZ_FREE(inserted_text); return false; } - if (I.undo_vec->len) { - RzLineUndoEntry *prev_entry = rz_vector_tail(I.undo_vec); - if (I.undo_continue) { + if (line->undo_vec->len) { + RzLineUndoEntry *prev_entry = rz_vector_tail(line->undo_vec); + if (line->undo_continue) { new_entry.continuous_prev = prev_entry->continuous_next; } } - if (I.undo_cursor < I.undo_vec->len) { + if (line->undo_cursor < line->undo_vec->len) { // remove all entries after undo_cursor - for (int i = I.undo_cursor; i < I.undo_vec->len; ++i) { + for (int i = line->undo_cursor; i < line->undo_vec->len; ++i) { // free entries to avoid memory leak - RzLineUndoEntry *e = rz_vector_index_ptr(I.undo_vec, i); + RzLineUndoEntry *e = rz_vector_index_ptr(line->undo_vec, i); undo_entry_free(e, NULL); } - rz_vector_remove_range(I.undo_vec, I.undo_cursor, I.undo_vec->len - I.undo_cursor, NULL); + rz_vector_remove_range(line->undo_vec, line->undo_cursor, line->undo_vec->len - line->undo_cursor, NULL); } - rz_vector_push(I.undo_vec, &new_entry); - I.undo_cursor++; + rz_vector_push(line->undo_vec, &new_entry); + line->undo_cursor++; return true; } /* To group several entries into one undo action, call undo_continuous_entries_begin/end before and after the sequence of operations. */ -static void undo_continuous_entries_begin() { - I.undo_continue = true; +static void undo_continuous_entries_begin(RzLine *line) { + line->undo_continue = true; } -static void undo_continuous_entries_end() { - I.undo_continue = false; - if (!I.undo_vec->len) { +static void undo_continuous_entries_end(RzLine *line) { + line->undo_continue = false; + if (!line->undo_vec->len) { return; } - RzLineUndoEntry *e = rz_vector_tail(I.undo_vec); + RzLineUndoEntry *e = rz_vector_tail(line->undo_vec); // terminate e->continuous_next = false; } -static bool undo_nothing_to_do(bool is_redo) { - if (is_redo && I.undo_cursor == I.undo_vec->len) { +static bool undo_nothing_to_do(RzLine *line, bool is_redo) { + if (is_redo && line->undo_cursor == line->undo_vec->len) { return true; - } else if (!is_redo && I.undo_cursor == 0) { + } else if (!is_redo && line->undo_cursor == 0) { return true; } return false; } -static void line_do(const bool is_redo) { +static void line_do(RzLine *line, const bool is_redo) { RzLineUndoEntry *e = NULL; bool is_continuous; - if (!I.undo_vec) { - undo_reset(); + if (!line->undo_vec) { + undo_reset(line); return; } do { @@ -196,26 +197,26 @@ static void line_do(const bool is_redo) { int inserting_len = 0; int start, end; - if (undo_nothing_to_do(is_redo)) { + if (undo_nothing_to_do(line, is_redo)) { break; } // obtain entry and set is_continuous if (!is_redo) { // undo - e = rz_vector_index_ptr(I.undo_vec, I.undo_cursor - 1); - I.undo_cursor--; + e = rz_vector_index_ptr(line->undo_vec, line->undo_cursor - 1); + line->undo_cursor--; is_continuous = e->continuous_prev; } else { // redo - e = rz_vector_index_ptr(I.undo_vec, I.undo_cursor); - I.undo_cursor++; + e = rz_vector_index_ptr(line->undo_vec, line->undo_cursor); + line->undo_cursor++; is_continuous = e->continuous_next; } if (!is_undo_entry_valid(e)) { // undo_vec broken - undo_reset(); + undo_reset(line); break; } @@ -247,40 +248,40 @@ static void line_do(const bool is_redo) { // delete text start = e->offset; end = e->offset + deleting_len; - if (start < 0 || end > I.buffer.length) { - undo_reset(); + if (start < 0 || end > line->buffer.length) { + undo_reset(line); break; } - memmove(I.buffer.data + start, I.buffer.data + end, I.buffer.length - end); - I.buffer.length -= deleting_len; - I.buffer.data[I.buffer.length] = '\0'; - I.buffer.index = start; + memmove(line->buffer.data + start, line->buffer.data + end, line->buffer.length - end); + line->buffer.length -= deleting_len; + line->buffer.data[line->buffer.length] = '\0'; + line->buffer.index = start; } if (inserting_text) { // insert text start = e->offset; end = e->offset + inserting_len; - if (start < 0 || start > I.buffer.length) { - undo_reset(); + if (start < 0 || start > line->buffer.length) { + undo_reset(line); break; } - memmove(I.buffer.data + end, I.buffer.data + start, I.buffer.length - start); - memcpy(I.buffer.data + start, inserting_text, inserting_len); - I.buffer.length += inserting_len; - I.buffer.data[I.buffer.length] = '\0'; - I.buffer.index = end; + memmove(line->buffer.data + end, line->buffer.data + start, line->buffer.length - start); + memcpy(line->buffer.data + start, inserting_text, inserting_len); + line->buffer.length += inserting_len; + line->buffer.data[line->buffer.length] = '\0'; + line->buffer.index = end; } } while (is_continuous); return; } -static void line_undo() { - line_do(false); +static void line_undo(RzLine *line) { + line_do(line, false); } -static void line_redo() { - line_do(true); +static void line_redo(RzLine *line) { + line_do(line, true); } static inline bool is_word_break_char(char ch, bool mode) { @@ -297,15 +298,15 @@ static inline bool is_word_break_char(char ch, bool mode) { } /* https://www.gnu.org/software/bash/manual/html_node/Commands-For-Killing.html */ -static void backward_kill_word(BreakMode mode) { +static void backward_kill_word(RzLine *line, BreakMode mode) { int i, len; - if (I.buffer.index <= 0) { + if (line->buffer.index <= 0) { return; } - for (i = I.buffer.index; i > 0 && is_word_break_char(I.buffer.data[i], mode); i--) { + for (i = line->buffer.index; i > 0 && is_word_break_char(line->buffer.data[i], mode); i--) { /* Move the cursor index back until we hit a non-word-break-character */ } - for (; i > 0 && !is_word_break_char(I.buffer.data[i], mode); i--) { + for (; i > 0 && !is_word_break_char(line->buffer.data[i], mode); i--) { /* Move the cursor index back until we hit a word-break-character */ } if (i > 0) { @@ -313,105 +314,108 @@ static void backward_kill_word(BreakMode mode) { } else if (i < 0) { i = 0; } - if (I.buffer.index > I.buffer.length) { - I.buffer.length = I.buffer.index; - } - len = I.buffer.index - i; - free(I.clipboard); - I.clipboard = rz_str_ndup(I.buffer.data + i, len); - rz_line_clipboard_push(I.clipboard); - memmove(I.buffer.data + i, I.buffer.data + I.buffer.index, - I.buffer.length - I.buffer.index + 1); - undo_add_entry(i, rz_str_ndup(I.clipboard, len), NULL); - I.buffer.length = strlen(I.buffer.data); - I.buffer.index = i; + if (line->buffer.index > line->buffer.length) { + line->buffer.length = line->buffer.index; + } + len = line->buffer.index - i; + free(line->clipboard); + line->clipboard = rz_str_ndup(line->buffer.data + i, len); + rz_line_clipboard_push(line, line->clipboard); + memmove(line->buffer.data + i, line->buffer.data + line->buffer.index, + line->buffer.length - line->buffer.index + 1); + undo_add_entry(line, i, rz_str_ndup(line->clipboard, len), NULL); + line->buffer.length = strlen(line->buffer.data); + line->buffer.index = i; } -static void kill_word(BreakMode mode) { +static void kill_word(RzLine *line, BreakMode mode) { int i, len; - for (i = I.buffer.index; i < I.buffer.length && is_word_break_char(I.buffer.data[i], mode); i++) { + for (i = line->buffer.index; i < line->buffer.length && is_word_break_char(line->buffer.data[i], mode); i++) { /* Move the cursor index forward until we hit a non-word-break-character */ } - for (; i < I.buffer.length && !is_word_break_char(I.buffer.data[i], mode); i++) { + for (; i < line->buffer.length && !is_word_break_char(line->buffer.data[i], mode); i++) { /* Move the cursor index forward until we hit a word-break-character */ } - len = i - I.buffer.index; - free(I.clipboard); - I.clipboard = rz_str_ndup(I.buffer.data + I.buffer.index, len); - rz_line_clipboard_push(I.clipboard); - memmove(I.buffer.data + I.buffer.index, I.buffer.data + i, I.buffer.length - i + 1); - undo_add_entry(i, rz_str_ndup(I.clipboard, len), NULL); - I.buffer.length -= len; + len = i - line->buffer.index; + free(line->clipboard); + line->clipboard = rz_str_ndup(line->buffer.data + line->buffer.index, len); + rz_line_clipboard_push(line, line->clipboard); + memmove(line->buffer.data + line->buffer.index, line->buffer.data + i, line->buffer.length - i + 1); + undo_add_entry(line, i, rz_str_ndup(line->clipboard, len), NULL); + line->buffer.length -= len; } -static void paste(bool *enable_yank_pop) { - if (I.clipboard) { - char *cursor = I.buffer.data + I.buffer.index; - int dist = (I.buffer.data + I.buffer.length) - cursor; - int len = strlen(I.clipboard); - I.buffer.length += len; - memmove(cursor + len, cursor, dist); - memcpy(cursor, I.clipboard, len); - undo_add_entry(I.buffer.index, NULL, rz_str_ndup(I.clipboard, len)); - I.buffer.index += len; - *enable_yank_pop = true; +static void paste(RzLine *line, bool *enable_yank_pop) { + if (!line->clipboard) { + return; } + char *cursor = line->buffer.data + line->buffer.index; + int dist = (line->buffer.data + line->buffer.length) - cursor; + int len = strlen(line->clipboard); + line->buffer.length += len; + memmove(cursor + len, cursor, dist); + memcpy(cursor, line->clipboard, len); + undo_add_entry(line, line->buffer.index, NULL, rz_str_ndup(line->clipboard, len)); + line->buffer.index += len; + *enable_yank_pop = true; } -static void unix_word_rubout(void) { +static void unix_word_rubout(RzLine *line) { int i, len; - if (I.buffer.index > 0) { - for (i = I.buffer.index - 1; i > 0 && I.buffer.data[i] == ' '; i--) { - /* Move cursor backwards until we hit a non-space character or EOL */ - /* This removes any trailing spaces from the input */ - } - for (; i > 0 && I.buffer.data[i] != ' '; i--) { - /* Move cursor backwards until we hit a space character or EOL */ - /* This deletes everything back to the previous space character */ - } - if (i > 0) { - i++; - } else if (i < 0) { - i = 0; - } - if (I.buffer.index > I.buffer.length) { - I.buffer.length = I.buffer.index; - } - len = I.buffer.index - i; - I.clipboard = rz_str_ndup(I.buffer.data + i, len); - rz_line_clipboard_push(I.clipboard); - undo_add_entry(i, rz_str_ndup(I.clipboard, len), NULL); - memmove(I.buffer.data + i, - I.buffer.data + I.buffer.index, - I.buffer.length - I.buffer.index + 1); - I.buffer.length = strlen(I.buffer.data); - I.buffer.index = i; + if (line->buffer.index < 1) { + return; + } + for (i = line->buffer.index - 1; i > 0 && line->buffer.data[i] == ' '; i--) { + /* Move cursor backwards until we hit a non-space character or EOL */ + /* This removes any trailing spaces from the input */ + } + for (; i > 0 && line->buffer.data[i] != ' '; i--) { + /* Move cursor backwards until we hit a space character or EOL */ + /* This deletes everything back to the previous space character */ + } + if (i > 0) { + i++; + } else if (i < 0) { + i = 0; } + if (line->buffer.index > line->buffer.length) { + line->buffer.length = line->buffer.index; + } + len = line->buffer.index - i; + line->clipboard = rz_str_ndup(line->buffer.data + i, len); + rz_line_clipboard_push(line, line->clipboard); + undo_add_entry(line, i, rz_str_ndup(line->clipboard, len), NULL); + memmove(line->buffer.data + i, + line->buffer.data + line->buffer.index, + line->buffer.length - line->buffer.index + 1); + line->buffer.length = strlen(line->buffer.data); + line->buffer.index = i; } -static int inithist(void) { - ZERO_FILL(I.history); - if ((I.history.size + 1024) * sizeof(char *) < I.history.size) { +static int inithist(RzLine *line) { + ZERO_FILL(line->history); + if ((line->history.size + 1024) * sizeof(char *) < line->history.size) { return false; } - I.history.data = (char **)calloc((I.history.size + 1024), sizeof(char *)); - if (!I.history.data) { + line->history.data = (char **)calloc((line->history.size + 1024), sizeof(char *)); + if (!line->history.data) { return false; } - I.history.size = RZ_LINE_HISTSIZE; + line->history.size = RZ_LINE_HISTSIZE; return true; } /* initialize history stuff */ -RZ_API bool rz_line_dietline_init(void) { - ZERO_FILL(I.completion); - if (!inithist()) { +RZ_API bool rz_line_dietline_init(RZ_NONNULL RzLine *line) { + rz_return_val_if_fail(line, false); + ZERO_FILL(line->completion); + if (!inithist(line)) { return false; } - if (!undo_reset()) { + if (!undo_reset(line)) { return false; } - I.echo = true; + line->echo = true; return true; } @@ -455,7 +459,8 @@ static int rz_line_readchar_utf8(ut8 *s, int maxlen) { return len; } -RZ_API int rz_line_set_hist_callback(RzLine *line, RzLineHistoryUpCb up, RzLineHistoryDownCb down) { +RZ_API int rz_line_set_hist_callback(RZ_NONNULL RzLine *line, RzLineHistoryUpCb up, RzLineHistoryDownCb down) { + rz_return_val_if_fail(line, -1); line->cb_history_up = up; line->cb_history_down = down; line->offset_hist_index = 0; @@ -479,12 +484,13 @@ static void setup_hist_match(RzLine *line) { line->history.do_setup_match = false; } -RZ_API int rz_line_hist_cmd_up(RzLine *line) { +RZ_API int rz_line_hist_cmd_up(RZ_NONNULL RzLine *line) { + rz_return_val_if_fail(line, -1); if (line->hist_up) { return line->hist_up(line->user); } if (!line->history.data) { - inithist(); + inithist(line); } if (line->history.index > 0 && line->history.data) { setup_hist_match(line); @@ -509,12 +515,13 @@ RZ_API int rz_line_hist_cmd_up(RzLine *line) { return false; } -RZ_API int rz_line_hist_cmd_down(RzLine *line) { +RZ_API int rz_line_hist_cmd_down(RZ_NONNULL RzLine *line) { + rz_return_val_if_fail(line, -1); if (line->hist_down) { return line->hist_down(line->user); } if (!line->history.data) { - inithist(); + inithist(line); } setup_hist_match(line); if (line->history.match) { @@ -545,89 +552,95 @@ RZ_API int rz_line_hist_cmd_down(RzLine *line) { return true; } -RZ_API int rz_line_hist_add(const char *line) { - if (!line || !*line) { +RZ_API bool rz_line_hist_add(RZ_NONNULL RzLine *line, RZ_NONNULL const char *str) { + rz_return_val_if_fail(line && str, -1); + if (RZ_STR_ISEMPTY(str)) { return false; } - if (!I.history.data) { - inithist(); + if (!line->history.data) { + inithist(line); } /* ignore dup */ - if (I.history.top > 0) { - const char *data = I.history.data[I.history.top - 1]; - if (data && !strcmp(line, data)) { - I.history.index = I.history.top; + if (line->history.top > 0) { + const char *data = line->history.data[line->history.top - 1]; + if (data && !strcmp(str, data)) { + line->history.index = line->history.top; return false; } } - if (I.history.top == I.history.size) { + if (line->history.top == line->history.size) { int i; - free(I.history.data[0]); - for (i = 0; i <= I.history.size - 2; i++) { - I.history.data[i] = I.history.data[i + 1]; + free(line->history.data[0]); + for (i = 0; i <= line->history.size - 2; i++) { + line->history.data[i] = line->history.data[i + 1]; } - I.history.top--; + line->history.top--; } - I.history.data[I.history.top++] = strdup(line); - I.history.index = I.history.top; + line->history.data[line->history.top++] = strdup(str); + line->history.index = line->history.top; return true; } -static int rz_line_hist_up(void) { - if (!I.cb_history_up) { - rz_line_set_hist_callback(&I, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); +static int rz_line_hist_up(RzLine *line) { + if (!line->cb_history_up) { + rz_line_set_hist_callback(line, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); } - return I.cb_history_up(&I); + return line->cb_history_up(line); } -static int rz_line_hist_down(void) { - if (!I.cb_history_down) { - rz_line_set_hist_callback(&I, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); +static int rz_line_hist_down(RzLine *line) { + if (!line->cb_history_down) { + rz_line_set_hist_callback(line, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); } - return I.cb_history_down(&I); + return line->cb_history_down(line); } -RZ_API const char *rz_line_hist_get(int n) { +RZ_API const char *rz_line_hist_get(RZ_NONNULL RzLine *line, int n) { + rz_return_val_if_fail(line, NULL); int i = 0; - if (!I.history.data) { - inithist(); + if (!line->history.data) { + inithist(line); } n--; - if (I.history.data) { - for (i = 0; i < I.history.size && I.history.data[i]; i++) { + if (line->history.data) { + for (i = 0; i < line->history.size && line->history.data[i]; i++) { if (n == i) { - return I.history.data[i]; + return line->history.data[i]; } } } return NULL; } -RZ_API int rz_line_hist_list(void) { +RZ_API int rz_line_hist_list(RZ_NONNULL RzLine *line) { + rz_return_val_if_fail(line, -1); int i = 0; - if (!I.history.data) { - inithist(); + if (!line->history.data) { + inithist(line); } - if (I.history.data) { - for (i = 0; i < I.history.size && I.history.data[i]; i++) { + if (line->history.data) { + for (i = 0; i < line->history.size && line->history.data[i]; i++) { // when you execute a command, you always move the history // by 1 before actually printing it. - rz_cons_printf("%5d %s\n", i + 1, I.history.data[i]); + rz_cons_printf("%5d %s\n", i + 1, line->history.data[i]); } } return i; } -RZ_API void rz_line_hist_free(void) { +RZ_API void rz_line_hist_free(RZ_NULLABLE RzLine *line) { + if (!line) { + return; + } int i; - if (I.history.data) { - for (i = 0; i < I.history.size; i++) { - RZ_FREE(I.history.data[i]); + if (line->history.data) { + for (i = 0; i < line->history.size; i++) { + RZ_FREE(line->history.data[i]); } } - RZ_FREE(I.history.data); - RZ_FREE(I.sdbshell_hist); - I.history.index = 0; + RZ_FREE(line->history.data); + RZ_FREE(line->sdbshell_hist); + line->history.index = 0; } /** @@ -637,7 +650,7 @@ RZ_API void rz_line_hist_free(void) { * were saved in a previous session * \return false(0) if it fails, true(!0) otherwise */ -RZ_API int rz_line_hist_load(RZ_NONNULL const char *path) { +RZ_API bool rz_line_hist_load(RZ_NONNULL RzLine *line, RZ_NONNULL const char *path) { rz_return_val_if_fail(path, false); FILE *fd; @@ -647,7 +660,7 @@ RZ_API int rz_line_hist_load(RZ_NONNULL const char *path) { } while (fgets(buf, sizeof(buf), fd) != NULL) { rz_str_trim_tail(buf); - rz_line_hist_add(buf); + rz_line_hist_add(line, buf); } fclose(fd); return true; @@ -660,7 +673,8 @@ RZ_API int rz_line_hist_load(RZ_NONNULL const char *path) { * will be saved * \return false(0) if it fails, true(!0) otherwise */ -RZ_API int rz_line_hist_save(RZ_NONNULL const char *path) { +RZ_API bool rz_line_hist_save(RZ_NONNULL RzLine *line, const char *path) { + rz_return_val_if_fail(line, false); FILE *fd; int i, ret = false; if (RZ_STR_ISEMPTY(path)) { @@ -677,9 +691,9 @@ RZ_API int rz_line_hist_save(RZ_NONNULL const char *path) { } fd = rz_sys_fopen(path, "w"); if (fd != NULL) { - if (I.history.data) { - for (i = 0; i < I.history.index; i++) { - fputs(I.history.data[i], fd); + if (line->history.data) { + for (i = 0; i < line->history.index; i++) { + fputs(line->history.data[i], fd); fputs("\n", fd); } fclose(fd); @@ -691,15 +705,16 @@ RZ_API int rz_line_hist_save(RZ_NONNULL const char *path) { return ret; } -RZ_API int rz_line_hist_chop(const char *file, int limit) { +RZ_API int rz_line_hist_chop(RZ_NONNULL RzLine *line, const char *file, int limit) { + rz_return_val_if_fail(line, -1); /* TODO */ return 0; } -static void selection_widget_draw(void) { +static void selection_widget_draw(RzLine *line) { RzCons *cons = rz_cons_singleton(); - RzSelWidget *sel_widget = I.sel_widget; - int y, pos_y, pos_x = rz_str_ansi_len(I.prompt); + RzSelWidget *sel_widget = line->sel_widget; + int y, pos_y, pos_x = rz_str_ansi_len(line->prompt); sel_widget->h = RZ_MIN(sel_widget->h, RZ_SELWIDGET_MAXH); for (y = 0; y < sel_widget->options_len; y++) { sel_widget->w = RZ_MAX(sel_widget->w, strlen(sel_widget->options[y])); @@ -743,126 +758,122 @@ static void selection_widget_draw(void) { } } - rz_cons_gotoxy(pos_x + I.buffer.length, pos_y); + rz_cons_gotoxy(pos_x + line->buffer.length, pos_y); rz_cons_memcat(Color_RESET_BG, 5); rz_cons_flush(); } -static void selection_widget_up(int steps) { - RzSelWidget *sel_widget = I.sel_widget; - if (sel_widget) { - if (sel_widget->direction == RZ_SELWIDGET_DIR_UP) { - int height = RZ_MIN(sel_widget->h, RZ_SELWIDGET_MAXH - 1); - sel_widget->selection = RZ_MIN(sel_widget->selection + steps, sel_widget->options_len - 1); - if (steps == 1) { - sel_widget->scroll = RZ_MIN(sel_widget->scroll + 1, RZ_SELWIDGET_MAXH - 1); - } else if (sel_widget->selection + (height - sel_widget->scroll) > sel_widget->options_len - 1) { - sel_widget->scroll = height - (sel_widget->options_len - 1 - sel_widget->selection); - } - } else { - sel_widget->selection = RZ_MAX(sel_widget->selection - steps, 0); - if (steps == 1) { - sel_widget->scroll = RZ_MAX(sel_widget->scroll - 1, 0); - } else if (sel_widget->selection - sel_widget->scroll <= 0) { - sel_widget->scroll = sel_widget->selection; - } +static void selection_widget_up(RzLine *line, int steps) { + RzSelWidget *sel_widget = line->sel_widget; + if (!sel_widget) { + return; + } + if (sel_widget->direction == RZ_SELWIDGET_DIR_UP) { + int height = RZ_MIN(sel_widget->h, RZ_SELWIDGET_MAXH - 1); + sel_widget->selection = RZ_MIN(sel_widget->selection + steps, sel_widget->options_len - 1); + if (steps == 1) { + sel_widget->scroll = RZ_MIN(sel_widget->scroll + 1, RZ_SELWIDGET_MAXH - 1); + } else if (sel_widget->selection + (height - sel_widget->scroll) > sel_widget->options_len - 1) { + sel_widget->scroll = height - (sel_widget->options_len - 1 - sel_widget->selection); + } + } else { + sel_widget->selection = RZ_MAX(sel_widget->selection - steps, 0); + if (steps == 1) { + sel_widget->scroll = RZ_MAX(sel_widget->scroll - 1, 0); + } else if (sel_widget->selection - sel_widget->scroll <= 0) { + sel_widget->scroll = sel_widget->selection; } } } -static void selection_widget_down(int steps) { - RzSelWidget *sel_widget = I.sel_widget; - if (sel_widget) { - if (sel_widget->direction == RZ_SELWIDGET_DIR_UP) { - sel_widget->selection = RZ_MAX(sel_widget->selection - steps, 0); - if (steps == 1) { - sel_widget->scroll = RZ_MAX(sel_widget->scroll - 1, 0); - } else if (sel_widget->selection - sel_widget->scroll <= 0) { - sel_widget->scroll = sel_widget->selection; - } - } else { - int height = RZ_MIN(sel_widget->h, RZ_SELWIDGET_MAXH - 1); - sel_widget->selection = RZ_MIN(sel_widget->selection + steps, sel_widget->options_len - 1); - if (steps == 1) { - sel_widget->scroll = RZ_MIN(sel_widget->scroll + 1, RZ_SELWIDGET_MAXH - 1); - } else if (sel_widget->selection + (height - sel_widget->scroll) > sel_widget->options_len - 1) { - sel_widget->scroll = height - (sel_widget->options_len - 1 - sel_widget->selection); - } +static void selection_widget_down(RzLine *line, int steps) { + RzSelWidget *sel_widget = line->sel_widget; + if (!sel_widget) { + return; + } + if (sel_widget->direction == RZ_SELWIDGET_DIR_UP) { + sel_widget->selection = RZ_MAX(sel_widget->selection - steps, 0); + if (steps == 1) { + sel_widget->scroll = RZ_MAX(sel_widget->scroll - 1, 0); + } else if (sel_widget->selection - sel_widget->scroll <= 0) { + sel_widget->scroll = sel_widget->selection; + } + } else { + int height = RZ_MIN(sel_widget->h, RZ_SELWIDGET_MAXH - 1); + sel_widget->selection = RZ_MIN(sel_widget->selection + steps, sel_widget->options_len - 1); + if (steps == 1) { + sel_widget->scroll = RZ_MIN(sel_widget->scroll + 1, RZ_SELWIDGET_MAXH - 1); + } else if (sel_widget->selection + (height - sel_widget->scroll) > sel_widget->options_len - 1) { + sel_widget->scroll = height - (sel_widget->options_len - 1 - sel_widget->selection); } } } -static void print_rline_task(void *_core) { - rz_cons_clear_line(0); - rz_cons_printf("%s%s%s", Color_RESET, I.prompt, I.buffer.data); - rz_cons_flush(); -} - -static void selection_widget_erase(void) { - RzSelWidget *sel_widget = I.sel_widget; +static void selection_widget_erase(RzLine *line) { + RzSelWidget *sel_widget = line->sel_widget; if (sel_widget) { - sel_widget->options_len = 0; - sel_widget->selection = -1; - selection_widget_draw(); - RZ_FREE(I.sel_widget); - RzCons *cons = rz_cons_singleton(); - if (cons->event_resize && cons->event_data) { - cons->event_resize(cons->event_data); - RzCore *core = (RzCore *)(cons->user); - if (core) { - cons->cb_task_oneshot(&core->tasks, print_rline_task, core); - } + return; + } + sel_widget->options_len = 0; + sel_widget->selection = -1; + selection_widget_draw(line); + RZ_FREE(line->sel_widget); + RzCons *cons = rz_cons_singleton(); + if (cons->event_resize && cons->event_data) { + cons->event_resize(cons->event_data); + RzCore *core = (RzCore *)(cons->user); + if (core) { + cons->cb_task_oneshot(line, NULL, &core->tasks); } - printf("%s", RZ_CONS_CLEAR_FROM_CURSOR_TO_END); } + printf("%s", RZ_CONS_CLEAR_FROM_CURSOR_TO_END); } -static void selection_widget_select(void) { - RzSelWidget *sel_widget = I.sel_widget; +static void selection_widget_select(RzLine *line) { + RzSelWidget *sel_widget = line->sel_widget; if (sel_widget && sel_widget->selection < sel_widget->options_len) { - char *sp = strchr(I.buffer.data, ' '); + char *sp = strchr(line->buffer.data, ' '); if (sp) { - int delta = sp - I.buffer.data + 1; - I.buffer.length = RZ_MIN(delta + strlen(sel_widget->options[sel_widget->selection]), RZ_LINE_BUFSIZE - 1); - memcpy(I.buffer.data + delta, sel_widget->options[sel_widget->selection], strlen(sel_widget->options[sel_widget->selection])); - I.buffer.index = I.buffer.length; + int delta = sp - line->buffer.data + 1; + line->buffer.length = RZ_MIN(delta + strlen(sel_widget->options[sel_widget->selection]), RZ_LINE_BUFSIZE - 1); + memcpy(line->buffer.data + delta, sel_widget->options[sel_widget->selection], strlen(sel_widget->options[sel_widget->selection])); + line->buffer.index = line->buffer.length; return; } - char *del_text = strdup(I.buffer.data); - I.buffer.length = RZ_MIN(strlen(sel_widget->options[sel_widget->selection]), RZ_LINE_BUFSIZE - 1); - memcpy(I.buffer.data, sel_widget->options[sel_widget->selection], I.buffer.length); - I.buffer.data[I.buffer.length] = '\0'; - I.buffer.index = I.buffer.length; - undo_add_entry(0, del_text, strdup(I.buffer.data)); - selection_widget_erase(); + char *del_text = strdup(line->buffer.data); + line->buffer.length = RZ_MIN(strlen(sel_widget->options[sel_widget->selection]), RZ_LINE_BUFSIZE - 1); + memcpy(line->buffer.data, sel_widget->options[sel_widget->selection], line->buffer.length); + line->buffer.data[line->buffer.length] = '\0'; + line->buffer.index = line->buffer.length; + undo_add_entry(line, 0, del_text, strdup(line->buffer.data)); + selection_widget_erase(NULL); } } -static void selection_widget_update(void) { - int argc = rz_pvector_len(&I.completion.args); - const char **argv = (const char **)rz_pvector_data(&I.completion.args); - if (argc == 0 || (argc == 1 && I.buffer.length >= strlen(argv[0]))) { - selection_widget_erase(); +static void selection_widget_update(RzLine *line) { + int argc = rz_pvector_len(&line->completion.args); + const char **argv = (const char **)rz_pvector_data(&line->completion.args); + if (argc == 0 || (argc == 1 && line->buffer.length >= strlen(argv[0]))) { + selection_widget_erase(line); return; } - if (!I.sel_widget) { + if (!line->sel_widget) { RzSelWidget *sel_widget = RZ_NEW0(RzSelWidget); - I.sel_widget = sel_widget; + line->sel_widget = sel_widget; } - I.sel_widget->scroll = 0; - I.sel_widget->selection = 0; - I.sel_widget->options_len = argc; - I.sel_widget->options = argv; - I.sel_widget->h = RZ_MAX(I.sel_widget->h, I.sel_widget->options_len); + line->sel_widget->scroll = 0; + line->sel_widget->selection = 0; + line->sel_widget->options_len = argc; + line->sel_widget->options = argv; + line->sel_widget->h = RZ_MAX(line->sel_widget->h, line->sel_widget->options_len); - if (I.prompt_type == RZ_LINE_PROMPT_DEFAULT) { - I.sel_widget->direction = RZ_SELWIDGET_DIR_DOWN; + if (line->prompt_type == RZ_LINE_PROMPT_DEFAULT) { + line->sel_widget->direction = RZ_SELWIDGET_DIR_DOWN; } else { - I.sel_widget->direction = RZ_SELWIDGET_DIR_UP; + line->sel_widget->direction = RZ_SELWIDGET_DIR_UP; } - selection_widget_draw(); + selection_widget_draw(line); rz_cons_flush(); - return; } static bool is_valid_buffer_limits(RzLineBuffer *buf, size_t start, size_t end, size_t s_len) { @@ -878,7 +889,7 @@ static bool is_valid_buffer_limits(RzLineBuffer *buf, size_t start, size_t end, return true; } -static void replace_buffer_text(RzLineBuffer *buf, size_t start, size_t end, const char *s) { +static void replace_buffer_text(RzLine *line, RzLineBuffer *buf, size_t start, size_t end, const char *s) { size_t s_len = strlen(s); if (!is_valid_buffer_limits(buf, start, end, s_len)) { return; @@ -889,7 +900,7 @@ static void replace_buffer_text(RzLineBuffer *buf, size_t start, size_t end, con char *del_text = rz_str_ndup(buf->data + start, diff); char *ins_text = rz_str_ndup(s, s_len); if (diff != s_len || rz_str_cmp(del_text, ins_text, diff)) { - undo_add_entry(start, del_text, ins_text); + undo_add_entry(line, start, del_text, ins_text); } else { RZ_FREE(del_text); RZ_FREE(ins_text); @@ -952,7 +963,8 @@ static void print_options(int argc, const char **argv) { rz_cons_printf("\n"); } -RZ_API void rz_line_autocomplete(void) { +RZ_API void rz_line_autocomplete(RZ_NONNULL RzLine *line) { + rz_return_if_fail(line); char *p; char *del_text = NULL; const char **argv = NULL; @@ -960,74 +972,74 @@ RZ_API void rz_line_autocomplete(void) { bool opt = false; RzCons *cons = rz_cons_singleton(); - if (I.ns_completion.run) { - RzLineNSCompletionResult *res = I.ns_completion.run(&I.buffer, I.prompt_type, I.ns_completion.run_user); - undo_continuous_entries_begin(); + if (line->ns_completion.run) { + RzLineNSCompletionResult *res = line->ns_completion.run(&line->buffer, line->prompt_type, line->ns_completion.run_user); + undo_continuous_entries_begin(line); if (!res || rz_pvector_empty(&res->options)) { // do nothing } else if (rz_pvector_len(&res->options) == 1) { // if there is just one option, just use it - bool is_at_end = I.buffer.length == I.buffer.index; - replace_buffer_text(&I.buffer, res->start, res->end, rz_pvector_at(&res->options, 0)); + bool is_at_end = line->buffer.length == line->buffer.index; + replace_buffer_text(line, &line->buffer, res->start, res->end, rz_pvector_at(&res->options, 0)); if (is_at_end && res->end_string) { - replace_buffer_text(&I.buffer, I.buffer.length, I.buffer.length, res->end_string); + replace_buffer_text(line, &line->buffer, line->buffer.length, line->buffer.length, res->end_string); } } else { // otherwise find maxcommonprefix, print it, and then print options char *max_common_pfx = get_max_common_pfx(&res->options); - replace_buffer_text(&I.buffer, res->start, res->end, max_common_pfx); + replace_buffer_text(line, &line->buffer, res->start, res->end, max_common_pfx); free(max_common_pfx); - rz_cons_printf("%s%s\n", I.prompt, I.buffer.data); + rz_cons_printf("%s%s\n", line->prompt, line->buffer.data); print_options(rz_pvector_len(&res->options), (const char **)rz_pvector_data(&res->options)); } - undo_continuous_entries_end(); + undo_continuous_entries_end(line); rz_line_ns_completion_result_free(res); return; } /* prepare argc and argv */ - if (I.completion.run) { - I.completion.opt = false; - I.completion.run(&I.completion, &I.buffer, I.prompt_type, I.completion.run_user); - argc = rz_pvector_len(&I.completion.args); - argv = (const char **)rz_pvector_data(&I.completion.args); - opt = I.completion.opt; - } - if (I.sel_widget && !I.sel_widget->complete_common) { - selection_widget_update(); + if (line->completion.run) { + line->completion.opt = false; + line->completion.run(&line->completion, &line->buffer, line->prompt_type, line->completion.run_user); + argc = rz_pvector_len(&line->completion.args); + argv = (const char **)rz_pvector_data(&line->completion.args); + opt = line->completion.opt; + } + if (line->sel_widget && !line->sel_widget->complete_common) { + selection_widget_update(line); return; } if (opt) { - p = (char *)rz_sub_str_lchr(I.buffer.data, 0, I.buffer.index, '='); + p = (char *)rz_sub_str_lchr(line->buffer.data, 0, line->buffer.index, '='); } else { - p = (char *)rz_sub_str_lchr(I.buffer.data, 0, I.buffer.index, ' '); + p = (char *)rz_sub_str_lchr(line->buffer.data, 0, line->buffer.index, ' '); } if (!p) { - p = (char *)rz_sub_str_lchr(I.buffer.data, 0, I.buffer.index, '@'); // HACK FOR r2 + p = (char *)rz_sub_str_lchr(line->buffer.data, 0, line->buffer.index, '@'); // HACK FOR r2 } if (p) { p++; - plen = sizeof(I.buffer.data) - (int)(size_t)(p - I.buffer.data); + plen = sizeof(line->buffer.data) - (int)(size_t)(p - line->buffer.data); } else { - p = I.buffer.data; // XXX: removes current buffer - plen = sizeof(I.buffer.data); + p = line->buffer.data; // XXX: removes current buffer + plen = sizeof(line->buffer.data); } if (plen) { - del_text = rz_str_ndup(I.buffer.data, I.buffer.length); + del_text = rz_str_ndup(line->buffer.data, line->buffer.length); } /* autocomplete */ if (argc == 1) { - const char *end_word = rz_sub_str_rchr(I.buffer.data, - I.buffer.index, strlen(I.buffer.data), ' '); - const char *t = end_word != NULL ? end_word : I.buffer.data + I.buffer.index; + const char *end_word = rz_sub_str_rchr(line->buffer.data, + line->buffer.index, strlen(line->buffer.data), ' '); + const char *t = end_word != NULL ? end_word : line->buffer.data + line->buffer.index; int largv0 = strlen(argv[0] ? argv[0] : ""); size_t len_t = strlen(t); p[largv0] = '\0'; - if ((p - I.buffer.data) + largv0 + 1 + len_t < plen) { + if ((p - line->buffer.data) + largv0 + 1 + len_t < plen) { if (len_t > 0) { int tt = largv0; if (*t != ' ') { @@ -1043,13 +1055,13 @@ RZ_API void rz_line_autocomplete(void) { p[largv0 + 1] = '\0'; } } - I.buffer.length = strlen(I.buffer.data); - I.buffer.index = I.buffer.length; + line->buffer.length = strlen(line->buffer.data); + line->buffer.index = line->buffer.length; } } else if (argc > 0) { if (*p) { // TODO: avoid overflow - const char *t = I.buffer.data + I.buffer.index; + const char *t = line->buffer.data + line->buffer.index; const char *root = argv[0]; int min_common_len = strlen(root); size_t len_t = strlen(t); @@ -1076,228 +1088,229 @@ RZ_API void rz_line_autocomplete(void) { if (!len_t) { p[min_common_len] = '\0'; } - I.buffer.length = strlen(I.buffer.data); - I.buffer.index = (p - I.buffer.data) + min_common_len; + line->buffer.length = strlen(line->buffer.data); + line->buffer.index = (p - line->buffer.data) + min_common_len; } } - if (rz_str_cmp(del_text, I.buffer.data, I.buffer.length)) { - undo_add_entry(0, del_text, rz_str_ndup(I.buffer.data, I.buffer.length)); + if (rz_str_cmp(del_text, line->buffer.data, line->buffer.length)) { + undo_add_entry(line, 0, del_text, rz_str_ndup(line->buffer.data, line->buffer.length)); } else { RZ_FREE(del_text); } - if (I.prompt_type != RZ_LINE_PROMPT_DEFAULT || cons->show_autocomplete_widget) { - selection_widget_update(); - if (I.sel_widget) { - I.sel_widget->complete_common = false; + if (line->prompt_type != RZ_LINE_PROMPT_DEFAULT || cons->show_autocomplete_widget) { + selection_widget_update(line); + if (line->sel_widget) { + line->sel_widget->complete_common = false; } return; } /* show options */ - if (argc > 1 && I.echo) { - rz_cons_printf("%s%s\n", I.prompt, I.buffer.data); + if (argc > 1 && line->echo) { + rz_cons_printf("%s%s\n", line->prompt, line->buffer.data); print_options(argc, argv); } } -RZ_API const char *rz_line_readline(void) { - return rz_line_readline_cb(NULL, NULL); +RZ_API const char *rz_line_readline(RZ_NONNULL RzLine *line) { + rz_return_val_if_fail(line, NULL); + return rz_line_readline_cb(line, NULL, NULL); } -static inline void rotate_kill_ring(bool *enable_yank_pop) { +static inline void rotate_kill_ring(RzLine *line, bool *enable_yank_pop) { if (!*enable_yank_pop) { return; } - I.buffer.index -= strlen(rz_list_get_n(I.kill_ring, I.kill_ring_ptr)); - undo_continuous_entries_begin(); - undo_add_entry(I.buffer.index, rz_str_ndup(I.buffer.data + I.buffer.index, I.buffer.length - I.buffer.index), NULL); - I.buffer.data[I.buffer.index] = 0; - I.kill_ring_ptr -= 1; - if (I.kill_ring_ptr < 0) { - I.kill_ring_ptr = I.kill_ring->length - 1; - } - I.clipboard = rz_list_get_n(I.kill_ring, I.kill_ring_ptr); - paste(enable_yank_pop); - undo_continuous_entries_end(); + line->buffer.index -= strlen(rz_list_get_n(line->kill_ring, line->kill_ring_ptr)); + undo_continuous_entries_begin(line); + undo_add_entry(line, line->buffer.index, rz_str_ndup(line->buffer.data + line->buffer.index, line->buffer.length - line->buffer.index), NULL); + line->buffer.data[line->buffer.index] = 0; + line->kill_ring_ptr -= 1; + if (line->kill_ring_ptr < 0) { + line->kill_ring_ptr = line->kill_ring->length - 1; + } + line->clipboard = rz_list_get_n(line->kill_ring, line->kill_ring_ptr); + paste(line, enable_yank_pop); + undo_continuous_entries_end(line); } -static inline void __delete_next_char(void) { - if (I.buffer.index < I.buffer.length) { - undo_add_entry(I.buffer.index, rz_str_ndup(I.buffer.data + I.buffer.index, 1), NULL); - int len = rz_str_utf8_charsize(I.buffer.data + I.buffer.index); - memmove(I.buffer.data + I.buffer.index, - I.buffer.data + I.buffer.index + len, - strlen(I.buffer.data + I.buffer.index + 1) + 1); - I.buffer.length -= len; +static inline void __delete_next_char(RzLine *line) { + if (line->buffer.index < line->buffer.length) { + undo_add_entry(line, line->buffer.index, rz_str_ndup(line->buffer.data + line->buffer.index, 1), NULL); + int len = rz_str_utf8_charsize(line->buffer.data + line->buffer.index); + memmove(line->buffer.data + line->buffer.index, + line->buffer.data + line->buffer.index + len, + strlen(line->buffer.data + line->buffer.index + 1) + 1); + line->buffer.length -= len; } } -static inline void __delete_prev_char(void) { - if (I.buffer.index > 0) { - undo_add_entry(I.buffer.index - 1, rz_str_ndup(I.buffer.data + I.buffer.index - 1, 1), NULL); +static inline void __delete_prev_char(RzLine *line) { + if (line->buffer.index > 0) { + undo_add_entry(line, line->buffer.index - 1, rz_str_ndup(line->buffer.data + line->buffer.index - 1, 1), NULL); } - if (I.buffer.index < I.buffer.length) { - if (I.buffer.index > 0) { - size_t len = rz_str_utf8_charsize_prev(I.buffer.data + I.buffer.index, I.buffer.index); - I.buffer.index -= len; - memmove(I.buffer.data + I.buffer.index, - I.buffer.data + I.buffer.index + len, - strlen(I.buffer.data + I.buffer.index)); - I.buffer.length -= len; + if (line->buffer.index < line->buffer.length) { + if (line->buffer.index > 0) { + size_t len = rz_str_utf8_charsize_prev(line->buffer.data + line->buffer.index, line->buffer.index); + line->buffer.index -= len; + memmove(line->buffer.data + line->buffer.index, + line->buffer.data + line->buffer.index + len, + strlen(line->buffer.data + line->buffer.index)); + line->buffer.length -= len; } } else { - I.buffer.length -= rz_str_utf8_charsize_last(I.buffer.data); - I.buffer.index = I.buffer.length; - if (I.buffer.length < 0) { - I.buffer.length = 0; + line->buffer.length -= rz_str_utf8_charsize_last(line->buffer.data); + line->buffer.index = line->buffer.length; + if (line->buffer.length < 0) { + line->buffer.length = 0; } } - I.buffer.data[I.buffer.length] = '\0'; - if (I.buffer.index < 0) { - I.buffer.index = 0; + line->buffer.data[line->buffer.length] = '\0'; + if (line->buffer.index < 0) { + line->buffer.index = 0; } } -static inline void delete_till_end(void) { - if (I.buffer.index < I.buffer.length) { - undo_add_entry(I.buffer.index, strdup(I.buffer.data + I.buffer.index), NULL); +static inline void delete_till_end(RzLine *line) { + if (line->buffer.index < line->buffer.length) { + undo_add_entry(line, line->buffer.index, strdup(line->buffer.data + line->buffer.index), NULL); } - I.buffer.data[I.buffer.index] = '\0'; - I.buffer.length = I.buffer.index; - I.buffer.index = I.buffer.index > 0 ? I.buffer.index - 1 : 0; + line->buffer.data[line->buffer.index] = '\0'; + line->buffer.length = line->buffer.index; + line->buffer.index = line->buffer.index > 0 ? line->buffer.index - 1 : 0; } -static void __print_prompt(void) { +static void __print_prompt(RzLine *line) { RzCons *cons = rz_cons_singleton(); int columns = rz_cons_get_size(NULL) - 2; - int chars = strlen(I.buffer.data); - int len, i, cols = RZ_MAX(1, columns - rz_str_ansi_len(I.prompt) - 2); + int chars = strlen(line->buffer.data); + int len, i, cols = RZ_MAX(1, columns - rz_str_ansi_len(line->prompt) - 2); if (cons->line->prompt_type == RZ_LINE_PROMPT_OFFSET) { rz_cons_gotoxy(0, cons->rows); rz_cons_flush(); } rz_cons_clear_line(0); if (cons->context->color_mode > 0) { - printf("\r%s%s", Color_RESET, I.prompt); + printf("\r%s%s", Color_RESET, line->prompt); } else { - printf("\r%s", I.prompt); + printf("\r%s", line->prompt); } - fwrite(I.buffer.data, 1, RZ_MIN(cols, chars), stdout); - printf("\r%s", I.prompt); - if (I.buffer.index > cols) { + fwrite(line->buffer.data, 1, RZ_MIN(cols, chars), stdout); + printf("\r%s", line->prompt); + if (line->buffer.index > cols) { printf("< "); - i = I.buffer.index - cols; - if (i > sizeof(I.buffer.data)) { - i = sizeof(I.buffer.data) - 1; + i = line->buffer.index - cols; + if (i > sizeof(line->buffer.data)) { + i = sizeof(line->buffer.data) - 1; } } else { i = 0; } - len = I.buffer.index - i; - if (len > 0 && (i + len) <= I.buffer.length) { - fwrite(I.buffer.data + i, 1, len, stdout); + len = line->buffer.index - i; + if (len > 0 && (i + len) <= line->buffer.length) { + fwrite(line->buffer.data + i, 1, len, stdout); } fflush(stdout); } -static inline void __move_cursor_right(void) { - I.buffer.index = I.buffer.index < I.buffer.length - ? I.buffer.index + rz_str_utf8_charsize(I.buffer.data + I.buffer.index) - : I.buffer.length; +static inline void __move_cursor_right(RzLine *line) { + line->buffer.index = line->buffer.index < line->buffer.length + ? line->buffer.index + rz_str_utf8_charsize(line->buffer.data + line->buffer.index) + : line->buffer.length; } -static inline void __move_cursor_left(void) { - I.buffer.index = I.buffer.index - ? I.buffer.index - rz_str_utf8_charsize_prev(I.buffer.data + I.buffer.index, I.buffer.index) +static inline void __move_cursor_left(RzLine *line) { + line->buffer.index = line->buffer.index + ? line->buffer.index - rz_str_utf8_charsize_prev(line->buffer.data + line->buffer.index, line->buffer.index) : 0; } -static inline void vi_cmd_b(void) { +static inline void vi_cmd_b(RzLine *line) { int i; - for (i = I.buffer.index - 2; i >= 0; i--) { - if ((is_word_break_char(I.buffer.data[i], MINOR_BREAK) && !is_word_break_char(I.buffer.data[i], MAJOR_BREAK)) || (is_word_break_char(I.buffer.data[i - 1], MINOR_BREAK) && !is_word_break_char(I.buffer.data[i], MINOR_BREAK))) { - I.buffer.index = i; + for (i = line->buffer.index - 2; i >= 0; i--) { + if ((is_word_break_char(line->buffer.data[i], MINOR_BREAK) && !is_word_break_char(line->buffer.data[i], MAJOR_BREAK)) || (is_word_break_char(line->buffer.data[i - 1], MINOR_BREAK) && !is_word_break_char(line->buffer.data[i], MINOR_BREAK))) { + line->buffer.index = i; break; } } if (i < 0) { - I.buffer.index = 0; + line->buffer.index = 0; } } -static inline void vi_cmd_B(void) { +static inline void vi_cmd_B(RzLine *line) { int i; - for (i = I.buffer.index - 2; i >= 0; i--) { - if ((!is_word_break_char(I.buffer.data[i], MAJOR_BREAK) && is_word_break_char(I.buffer.data[i - 1], MAJOR_BREAK))) { - I.buffer.index = i; + for (i = line->buffer.index - 2; i >= 0; i--) { + if ((!is_word_break_char(line->buffer.data[i], MAJOR_BREAK) && is_word_break_char(line->buffer.data[i - 1], MAJOR_BREAK))) { + line->buffer.index = i; break; } } if (i < 0) { - I.buffer.index = 0; + line->buffer.index = 0; } } -static inline void vi_cmd_W(void) { +static inline void vi_cmd_W(RzLine *line) { int i; - for (i = I.buffer.index + 1; i < I.buffer.length; i++) { - if ((!is_word_break_char(I.buffer.data[i], MAJOR_BREAK) && is_word_break_char(I.buffer.data[i - 1], MAJOR_BREAK))) { - I.buffer.index = i; + for (i = line->buffer.index + 1; i < line->buffer.length; i++) { + if ((!is_word_break_char(line->buffer.data[i], MAJOR_BREAK) && is_word_break_char(line->buffer.data[i - 1], MAJOR_BREAK))) { + line->buffer.index = i; break; } } - if (i >= I.buffer.length) { - I.buffer.index = I.buffer.length - 1; + if (i >= line->buffer.length) { + line->buffer.index = line->buffer.length - 1; } } -static inline void vi_cmd_w(void) { +static inline void vi_cmd_w(RzLine *line) { int i; - for (i = I.buffer.index + 1; i < I.buffer.length; i++) { - if ((!is_word_break_char(I.buffer.data[i], MINOR_BREAK) && is_word_break_char(I.buffer.data[i - 1], MINOR_BREAK)) || (is_word_break_char(I.buffer.data[i], MINOR_BREAK) && !is_word_break_char(I.buffer.data[i], MAJOR_BREAK))) { - I.buffer.index = i; + for (i = line->buffer.index + 1; i < line->buffer.length; i++) { + if ((!is_word_break_char(line->buffer.data[i], MINOR_BREAK) && is_word_break_char(line->buffer.data[i - 1], MINOR_BREAK)) || (is_word_break_char(line->buffer.data[i], MINOR_BREAK) && !is_word_break_char(line->buffer.data[i], MAJOR_BREAK))) { + line->buffer.index = i; break; } } - if (i >= I.buffer.length) { - I.buffer.index = I.buffer.length - 1; + if (i >= line->buffer.length) { + line->buffer.index = line->buffer.length - 1; } } -static inline void vi_cmd_E(void) { +static inline void vi_cmd_E(RzLine *line) { int i; - for (i = I.buffer.index + 1; i < I.buffer.length; i++) { - if ((!is_word_break_char(I.buffer.data[i], MAJOR_BREAK) && is_word_break_char(I.buffer.data[i + 1], MAJOR_BREAK))) { - I.buffer.index = i; + for (i = line->buffer.index + 1; i < line->buffer.length; i++) { + if ((!is_word_break_char(line->buffer.data[i], MAJOR_BREAK) && is_word_break_char(line->buffer.data[i + 1], MAJOR_BREAK))) { + line->buffer.index = i; break; } } - if (i >= I.buffer.length) { - I.buffer.index = I.buffer.length - 1; + if (i >= line->buffer.length) { + line->buffer.index = line->buffer.length - 1; } } -static inline void vi_cmd_e(void) { +static inline void vi_cmd_e(RzLine *line) { int i; - for (i = I.buffer.index + 1; i < I.buffer.length; i++) { - if ((!is_word_break_char(I.buffer.data[i], MINOR_BREAK) && is_word_break_char(I.buffer.data[i + 1], MINOR_BREAK)) || (is_word_break_char(I.buffer.data[i], MINOR_BREAK) && !is_word_break_char(I.buffer.data[i], MAJOR_BREAK))) { - I.buffer.index = i; + for (i = line->buffer.index + 1; i < line->buffer.length; i++) { + if ((!is_word_break_char(line->buffer.data[i], MINOR_BREAK) && is_word_break_char(line->buffer.data[i + 1], MINOR_BREAK)) || (is_word_break_char(line->buffer.data[i], MINOR_BREAK) && !is_word_break_char(line->buffer.data[i], MAJOR_BREAK))) { + line->buffer.index = i; break; } } - if (i >= I.buffer.length) { - I.buffer.index = I.buffer.length - 1; + if (i >= line->buffer.length) { + line->buffer.index = line->buffer.length - 1; } } -static void __update_prompt_color(void) { +static void __update_prompt_color(RzLine *line) { RzCons *cons = rz_cons_singleton(); const char *BEGIN = "", *END = ""; if (cons->context->color_mode) { - if (I.prompt_mode) { - switch (I.vi_mode) { + if (line->prompt_mode) { + switch (line->vi_mode) { case CONTROL_MODE: BEGIN = cons->context->pal.invalid; break; @@ -1311,29 +1324,29 @@ static void __update_prompt_color(void) { } END = cons->context->pal.reset; } - char *prompt = rz_str_escape(I.prompt); // remote the color - free(I.prompt); - I.prompt = rz_str_newf("%s%s%s", BEGIN, prompt, END); + char *prompt = rz_str_escape(line->prompt); // remote the color + free(line->prompt); + line->prompt = rz_str_newf("%s%s%s", BEGIN, prompt, END); free(prompt); } -static void __vi_mode(bool *enable_yank_pop) { +static void __vi_mode(RzLine *line, bool *enable_yank_pop) { char ch; - I.vi_mode = CONTROL_MODE; - __update_prompt_color(); + line->vi_mode = CONTROL_MODE; + __update_prompt_color(line); const char *gcomp_line = ""; static int gcomp = 0; for (;;) { int rep = 0; - if (I.echo) { - __print_prompt(); + if (line->echo) { + __print_prompt(line); } - if (I.vi_mode != CONTROL_MODE) { // exit if insert mode is selected - __update_prompt_color(); + if (line->vi_mode != CONTROL_MODE) { // exit if insert mode is selected + __update_prompt_color(line); break; } - bool o_do_setup_match = I.history.do_setup_match; - I.history.do_setup_match = true; + bool o_do_setup_match = line->history.do_setup_match; + line->history.do_setup_match = true; ch = rz_cons_readchar(); while (IS_DIGIT(ch)) { // handle commands like 3b if (ch == '0' && rep == 0) { // to handle the command 0 @@ -1347,31 +1360,31 @@ static void __vi_mode(bool *enable_yank_pop) { switch (ch) { case 3: - if (I.hud) { - I.hud->activate = false; - I.hud->current_entry_n = -1; + if (line->hud) { + line->hud->activate = false; + line->hud->current_entry_n = -1; } - if (I.echo) { + if (line->echo) { eprintf("^C\n"); } - I.buffer.index = I.buffer.length = 0; - *I.buffer.data = '\0'; + line->buffer.index = line->buffer.length = 0; + *line->buffer.data = '\0'; gcomp = 0; return; case 'D': - delete_till_end(); + delete_till_end(line); break; case 'r': { char c = rz_cons_readchar(); - I.buffer.data[I.buffer.index] = c; + line->buffer.data[line->buffer.index] = c; } break; case 'x': while (rep--) { - __delete_next_char(); + __delete_next_char(line); } break; case 'c': - I.vi_mode = INSERT_MODE; // goto insert mode + line->vi_mode = INSERT_MODE; // goto insert mode /* fall through */ case 'd': { char c = rz_cons_readchar(); @@ -1380,157 +1393,158 @@ static void __vi_mode(bool *enable_yank_pop) { case 'i': { char t = rz_cons_readchar(); if (t == 'w') { // diw - kill_word(MINOR_BREAK); - backward_kill_word(MINOR_BREAK); + kill_word(line, MINOR_BREAK); + backward_kill_word(line, MINOR_BREAK); } else if (t == 'W') { // diW - kill_word(MAJOR_BREAK); - backward_kill_word(MINOR_BREAK); + kill_word(line, MAJOR_BREAK); + backward_kill_word(line, MINOR_BREAK); } - if (I.hud) { - I.hud->vi = false; + if (line->hud) { + line->hud->vi = false; } } break; case 'W': - kill_word(MAJOR_BREAK); + kill_word(line, MAJOR_BREAK); break; case 'w': - kill_word(MINOR_BREAK); + kill_word(line, MINOR_BREAK); break; case 'B': - backward_kill_word(MAJOR_BREAK); + backward_kill_word(line, MAJOR_BREAK); break; case 'b': - backward_kill_word(MINOR_BREAK); + backward_kill_word(line, MINOR_BREAK); break; case 'h': - __delete_prev_char(); + __delete_prev_char(line); break; case 'l': - __delete_next_char(); + __delete_next_char(line); break; case '$': - delete_till_end(); + delete_till_end(line); break; case '^': case '0': - strncpy(I.buffer.data, I.buffer.data + I.buffer.index, I.buffer.length); - I.buffer.length -= I.buffer.index; - I.buffer.index = 0; + strncpy(line->buffer.data, line->buffer.data + line->buffer.index, line->buffer.length); + line->buffer.length -= line->buffer.index; + line->buffer.index = 0; break; } - __print_prompt(); + __print_prompt(line); } } break; case 'I': - if (I.hud) { - I.hud->vi = false; + if (line->hud) { + line->hud->vi = false; } - I.vi_mode = INSERT_MODE; + line->vi_mode = INSERT_MODE; /* fall through */ case '^': case '0': if (gcomp) { - strcpy(I.buffer.data, gcomp_line); - I.buffer.length = strlen(I.buffer.data); - I.buffer.index = 0; + strcpy(line->buffer.data, gcomp_line); + line->buffer.length = strlen(line->buffer.data); + line->buffer.index = 0; gcomp = false; } - I.buffer.index = 0; + line->buffer.index = 0; break; case 'A': - I.vi_mode = INSERT_MODE; + line->vi_mode = INSERT_MODE; /* fall through */ case '$': if (gcomp) { - strcpy(I.buffer.data, gcomp_line); - I.buffer.index = strlen(I.buffer.data); - I.buffer.length = I.buffer.index; + strcpy(line->buffer.data, gcomp_line); + line->buffer.index = strlen(line->buffer.data); + line->buffer.length = line->buffer.index; gcomp = false; } else { - I.buffer.index = I.buffer.length; + line->buffer.index = line->buffer.length; } break; case 'p': while (rep--) { - paste(enable_yank_pop); + paste(line, enable_yank_pop); } break; case 'a': - __move_cursor_right(); + __move_cursor_right(line); /* fall through */ case 'i': - I.vi_mode = INSERT_MODE; - if (I.hud) { - I.hud->vi = false; + line->vi_mode = INSERT_MODE; + if (line->hud) { + line->hud->vi = false; } break; case 'h': while (rep--) { - __move_cursor_left(); + __move_cursor_left(line); } break; case 'l': while (rep--) { - __move_cursor_right(); + __move_cursor_right(line); } break; case 'E': while (rep--) { - vi_cmd_E(); + vi_cmd_E(line); } break; case 'e': while (rep--) { - vi_cmd_e(); + vi_cmd_e(line); } break; case 'B': while (rep--) { - vi_cmd_B(); + vi_cmd_B(line); } break; case 'b': while (rep--) { - vi_cmd_b(); + vi_cmd_b(line); } break; case 'W': while (rep--) { - vi_cmd_W(); + vi_cmd_W(line); } break; case 'w': while (rep--) { - vi_cmd_w(); + vi_cmd_w(line); } break; default: // escape key ch = tolower(rz_cons_arrow_to_hjkl(ch)); switch (ch) { case 'k': // up - I.history.do_setup_match = o_do_setup_match; - rz_line_hist_up(); + line->history.do_setup_match = o_do_setup_match; + rz_line_hist_up(line); break; case 'j': // down - I.history.do_setup_match = o_do_setup_match; - rz_line_hist_down(); + line->history.do_setup_match = o_do_setup_match; + rz_line_hist_down(line); break; case 'l': // right - __move_cursor_right(); + __move_cursor_right(line); break; case 'h': // left - __move_cursor_left(); + __move_cursor_left(line); break; } break; } - if (I.hud) { + if (line->hud) { return; } } } -RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { +RZ_API const char *rz_line_readline_cb(RZ_NONNULL RzLine *line, RzLineReadCallback cb, void *user) { + rz_return_val_if_fail(line, NULL); int rows; const char *gcomp_line = ""; static int gcomp_idx = 0; @@ -1546,36 +1560,36 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { RzCons *cons = rz_cons_singleton(); - if (!I.hud || (I.hud && !I.hud->activate)) { - I.buffer.index = I.buffer.length = 0; - I.buffer.data[0] = '\0'; - if (I.hud) { - I.hud->activate = true; + if (!line->hud || (line->hud && !line->hud->activate)) { + line->buffer.index = line->buffer.length = 0; + line->buffer.data[0] = '\0'; + if (line->hud) { + line->hud->activate = true; } } int mouse_status = cons->mouse; - if (I.hud && I.hud->vi) { - __vi_mode(&enable_yank_pop); + if (line->hud && line->hud->vi) { + __vi_mode(NULL, &enable_yank_pop); goto _end; } - if (I.contents) { - memmove(I.buffer.data, I.contents, - RZ_MIN(strlen(I.contents) + 1, RZ_LINE_BUFSIZE - 1)); - I.buffer.data[RZ_LINE_BUFSIZE - 1] = '\0'; - I.buffer.index = I.buffer.length = strlen(I.contents); + if (line->contents) { + memmove(line->buffer.data, line->contents, + RZ_MIN(strlen(line->contents) + 1, RZ_LINE_BUFSIZE - 1)); + line->buffer.data[RZ_LINE_BUFSIZE - 1] = '\0'; + line->buffer.index = line->buffer.length = strlen(line->contents); } - if (I.disable) { - if (!fgets(I.buffer.data, RZ_LINE_BUFSIZE, stdin)) { + if (line->disable) { + if (!fgets(line->buffer.data, RZ_LINE_BUFSIZE, stdin)) { return NULL; } - return (*I.buffer.data) ? I.buffer.data : rz_line_nullstr; + return (*line->buffer.data) ? line->buffer.data : rz_line_nullstr; } memset(&buf, 0, sizeof buf); rz_cons_set_raw(1); - if (I.echo) { - __print_prompt(); + if (line->echo) { + __print_prompt(line); } rz_cons_break_push(NULL, NULL); for (;;) { @@ -1583,12 +1597,12 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { if (rz_cons_is_breaked()) { break; } - I.buffer.data[I.buffer.length] = '\0'; + line->buffer.data[line->buffer.length] = '\0'; if (cb) { - int cbret = cb(user, I.buffer.data); + int cbret = cb(user, line->buffer.data); if (cbret == 0) { - I.buffer.data[0] = 0; - I.buffer.length = 0; + line->buffer.data[0] = 0; + line->buffer.length = 0; } } utflen = rz_line_readchar_utf8((ut8 *)buf, sizeof(buf)); @@ -1597,9 +1611,9 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { return NULL; } buf[utflen] = 0; - bool o_do_setup_match = I.history.do_setup_match; - I.history.do_setup_match = true; - if (I.echo) { + bool o_do_setup_match = line->history.do_setup_match; + line->history.do_setup_match = true; + if (line->echo) { rz_cons_clear_line(0); } switch (*buf) { @@ -1609,80 +1623,80 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { break; case 1: // ^A if (gcomp) { - strcpy(I.buffer.data, gcomp_line); - I.buffer.length = strlen(I.buffer.data); - I.buffer.index = 0; + strcpy(line->buffer.data, gcomp_line); + line->buffer.length = strlen(line->buffer.data); + line->buffer.index = 0; gcomp = false; } - I.buffer.index = 0; + line->buffer.index = 0; break; case 2: // ^b // emacs left - __move_cursor_left(); + __move_cursor_left(NULL); break; case 5: // ^E if (gcomp) { - strcpy(I.buffer.data, gcomp_line); - I.buffer.index = strlen(I.buffer.data); - I.buffer.length = I.buffer.index; + strcpy(line->buffer.data, gcomp_line); + line->buffer.index = strlen(line->buffer.data); + line->buffer.length = line->buffer.index; gcomp = false; } else if (prev == 24) { // ^X = 0x18 - I.buffer.data[I.buffer.length] = 0; // probably unnecessary - tmp_ed_cmd = I.cb_editor(I.user, I.buffer.data); + line->buffer.data[line->buffer.length] = 0; // probably unnecessary + tmp_ed_cmd = line->cb_editor(line->user, line->buffer.data); if (tmp_ed_cmd) { /* copied from yank (case 25) */ - I.buffer.length = strlen(tmp_ed_cmd); - if (I.buffer.length < RZ_LINE_BUFSIZE) { - I.buffer.index = I.buffer.length; - strncpy(I.buffer.data, tmp_ed_cmd, RZ_LINE_BUFSIZE - 1); - I.buffer.data[RZ_LINE_BUFSIZE - 1] = '\0'; - undo_add_entry(0, NULL, strdup(tmp_ed_cmd)); + line->buffer.length = strlen(tmp_ed_cmd); + if (line->buffer.length < RZ_LINE_BUFSIZE) { + line->buffer.index = line->buffer.length; + strncpy(line->buffer.data, tmp_ed_cmd, RZ_LINE_BUFSIZE - 1); + line->buffer.data[RZ_LINE_BUFSIZE - 1] = '\0'; + undo_add_entry(line, 0, NULL, strdup(tmp_ed_cmd)); } else { - I.buffer.length -= strlen(tmp_ed_cmd); + line->buffer.length -= strlen(tmp_ed_cmd); } free(tmp_ed_cmd); } } else { - I.buffer.index = I.buffer.length; + line->buffer.index = line->buffer.length; } break; case 3: // ^C - if (I.hud) { - I.hud->activate = false; - I.hud->current_entry_n = -1; + if (line->hud) { + line->hud->activate = false; + line->hud->current_entry_n = -1; } - if (I.echo) { + if (line->echo) { eprintf("^C\n"); } - I.buffer.index = I.buffer.length = 0; - *I.buffer.data = '\0'; + line->buffer.index = line->buffer.length = 0; + *line->buffer.data = '\0'; gcomp = 0; goto _end; case 4: // ^D - if (!I.buffer.data[0]) { /* eof */ - if (I.echo) { - __print_prompt(); + if (!line->buffer.data[0]) { /* eof */ + if (line->echo) { + __print_prompt(line); printf("\n"); } rz_cons_set_raw(false); rz_cons_break_pop(); return NULL; } - if (I.buffer.index < I.buffer.length) { - __delete_next_char(); + if (line->buffer.index < line->buffer.length) { + __delete_next_char(line); } break; case 11: // ^K - if (I.buffer.index != I.buffer.length) { - undo_add_entry(I.buffer.index, strdup(I.buffer.data + I.buffer.index), NULL); + if (line->buffer.index != line->buffer.length) { + undo_add_entry(line, line->buffer.index, strdup(line->buffer.data + line->buffer.index), NULL); } - I.buffer.data[I.buffer.index] = '\0'; - I.buffer.length = I.buffer.index; + line->buffer.data[line->buffer.index] = '\0'; + line->buffer.length = line->buffer.index; break; case 6: // ^f // emacs right - __move_cursor_right(); + __move_cursor_right(line); break; case 12: // ^L -- clear screen - if (I.echo) { + if (line->echo) { eprintf("\x1b[2J\x1b[0;0H"); } fflush(stdout); @@ -1701,19 +1715,19 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { } gcomp_is_rev = false; } else { - __move_cursor_left(); + __move_cursor_left(line); } break; case 21: // ^U - cut - free(I.clipboard); - I.clipboard = strdup(I.buffer.data); - rz_line_clipboard_push(I.clipboard); - if (I.buffer.length) { - undo_add_entry(0, strdup(I.clipboard), NULL); - } - I.buffer.data[0] = '\0'; - I.buffer.length = 0; - I.buffer.index = 0; + free(line->clipboard); + line->clipboard = strdup(line->buffer.data); + rz_line_clipboard_push(line, line->clipboard); + if (line->buffer.length) { + undo_add_entry(line, 0, strdup(line->clipboard), NULL); + } + line->buffer.data[0] = '\0'; + line->buffer.length = 0; + line->buffer.index = 0; break; #if __WINDOWS__ case 22: // ^V - Paste from windows clipboard @@ -1731,13 +1745,13 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { break; } int len = strlen(txt); - I.buffer.length += len; - if (I.buffer.length < RZ_LINE_BUFSIZE) { - undo_add_entry(I.buffer.index, NULL, strdup(txt)); - I.buffer.index = I.buffer.length; - strcat(I.buffer.data, txt); + line->buffer.length += len; + if (line->buffer.length < RZ_LINE_BUFSIZE) { + undo_add_entry(line, line->buffer.index, NULL, strdup(txt)); + line->buffer.index = line->buffer.length; + strcat(line->buffer.data, txt); } else { - I.buffer.length -= len; + line->buffer.length -= len; } free(txt); } @@ -1748,132 +1762,132 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { } break; #endif case 23: // ^W ^w unix-word-rubout - unix_word_rubout(); + unix_word_rubout(line); break; case 24: // ^X - if (I.buffer.index > 0) { - undo_add_entry(0, rz_str_ndup(I.buffer.data, I.buffer.index), NULL); - strncpy(I.buffer.data, I.buffer.data + I.buffer.index, I.buffer.length); - I.buffer.length -= I.buffer.index; - I.buffer.index = 0; + if (line->buffer.index > 0) { + undo_add_entry(line, 0, rz_str_ndup(line->buffer.data, line->buffer.index), NULL); + strncpy(line->buffer.data, line->buffer.data + line->buffer.index, line->buffer.length); + line->buffer.length -= line->buffer.index; + line->buffer.index = 0; } break; case 25: // ^Y - paste - paste(&enable_yank_pop); + paste(line, &enable_yank_pop); yank_flag = 1; break; case 29: // ^^ - rotate kill ring - rotate_kill_ring(&enable_yank_pop); + rotate_kill_ring(line, &enable_yank_pop); yank_flag = enable_yank_pop ? 1 : 0; break; case 20: // ^t Kill from point to the end of the current word, - kill_word(MINOR_BREAK); + kill_word(line, MINOR_BREAK); break; case 15: // ^o kill backward - backward_kill_word(MINOR_BREAK); + backward_kill_word(line, MINOR_BREAK); break; case 14: // ^n - if (I.hud) { - if (I.hud->top_entry_n + 1 < I.hud->current_entry_n) { - I.hud->top_entry_n++; + if (line->hud) { + if (line->hud->top_entry_n + 1 < line->hud->current_entry_n) { + line->hud->top_entry_n++; } - } else if (I.sel_widget) { - selection_widget_down(1); - selection_widget_draw(); + } else if (line->sel_widget) { + selection_widget_down(line, 1); + selection_widget_draw(line); } else if (gcomp) { if (gcomp_idx > 0) { gcomp_idx--; } } else { - undo_reset(); - I.history.do_setup_match = o_do_setup_match; - rz_line_hist_down(); + undo_reset(line); + line->history.do_setup_match = o_do_setup_match; + rz_line_hist_down(line); } break; case 16: // ^p - if (I.hud) { - if (I.hud->top_entry_n >= 0) { - I.hud->top_entry_n--; + if (line->hud) { + if (line->hud->top_entry_n >= 0) { + line->hud->top_entry_n--; } - } else if (I.sel_widget) { - selection_widget_up(1); - selection_widget_draw(); + } else if (line->sel_widget) { + selection_widget_up(line, 1); + selection_widget_draw(line); } else if (gcomp) { gcomp_idx++; } else { - undo_reset(); - I.history.do_setup_match = o_do_setup_match; - rz_line_hist_up(); + undo_reset(line); + line->history.do_setup_match = o_do_setup_match; + rz_line_hist_up(line); } break; case 31: // ^_ ctrl-/ or ctrl-_ - if (!gcomp && !I.hud && !I.sel_widget) { - line_undo(); + if (!gcomp && !line->hud && !line->sel_widget) { + line_undo(line); } break; case 27: // esc-5b-41-00-00 alt/meta key buf[0] = rz_cons_readchar_timeout(50); switch ((signed char)buf[0]) { case 127: // alt+bkspace - backward_kill_word(MINOR_BREAK); + backward_kill_word(line, MINOR_BREAK); break; case -1: // escape key, goto vi mode - if (I.enable_vi_mode) { - if (I.hud) { - I.hud->vi = true; + if (line->enable_vi_mode) { + if (line->hud) { + line->hud->vi = true; } - __vi_mode(&enable_yank_pop); + __vi_mode(line, &enable_yank_pop); }; - if (I.sel_widget) { - selection_widget_erase(); + if (line->sel_widget) { + selection_widget_erase(line); } break; case 1: // begin - I.buffer.index = 0; + line->buffer.index = 0; break; case 5: // end - I.buffer.index = I.buffer.length; + line->buffer.index = line->buffer.length; break; case 'B': case 'b': - for (i = I.buffer.index - 2; i >= 0; i--) { - if (is_word_break_char(I.buffer.data[i], MINOR_BREAK) && !is_word_break_char(I.buffer.data[i + 1], MINOR_BREAK)) { - I.buffer.index = i + 1; + for (i = line->buffer.index - 2; i >= 0; i--) { + if (is_word_break_char(line->buffer.data[i], MINOR_BREAK) && !is_word_break_char(line->buffer.data[i + 1], MINOR_BREAK)) { + line->buffer.index = i + 1; break; } } if (i < 0) { - I.buffer.index = 0; + line->buffer.index = 0; } break; case 'D': case 'd': - kill_word(MINOR_BREAK); + kill_word(line, MINOR_BREAK); break; case 'F': case 'f': // next word - for (i = I.buffer.index + 1; i < I.buffer.length; i++) { - if (!is_word_break_char(I.buffer.data[i], MINOR_BREAK) && is_word_break_char(I.buffer.data[i - 1], MINOR_BREAK)) { - I.buffer.index = i; + for (i = line->buffer.index + 1; i < line->buffer.length; i++) { + if (!is_word_break_char(line->buffer.data[i], MINOR_BREAK) && is_word_break_char(line->buffer.data[i - 1], MINOR_BREAK)) { + line->buffer.index = i; break; } } - if (i >= I.buffer.length) { - I.buffer.index = I.buffer.length; + if (i >= line->buffer.length) { + line->buffer.index = line->buffer.length; } break; case 63: // ^[? Meta-/ case 95: // ^[_ Meta-_ - if (!gcomp && !I.hud && !I.sel_widget) { - line_redo(); + if (!gcomp && !line->hud && !line->sel_widget) { + line_redo(line); } break; default: buf[1] = rz_cons_readchar_timeout(50); if (buf[1] == -1) { // alt+e rz_cons_break_pop(); - __print_prompt(); + __print_prompt(line); continue; } if (buf[0] == 'O' && strchr("ABCDFH", buf[1]) != NULL) { // O @@ -1882,7 +1896,7 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { if (buf[0] == 0x5b) { // [ switch (buf[1]) { case '3': // supr - __delete_next_char(); + __delete_next_char(line); buf[1] = rz_cons_readchar(); if (buf[1] == -1) { rz_cons_break_pop(); @@ -1891,42 +1905,42 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { break; case '5': // pag up buf[1] = rz_cons_readchar(); - if (I.hud) { + if (line->hud) { rz_cons_get_size(&rows); - I.hud->top_entry_n -= (rows - 1); - if (I.hud->top_entry_n < 0) { - I.hud->top_entry_n = 0; + line->hud->top_entry_n -= (rows - 1); + if (line->hud->top_entry_n < 0) { + line->hud->top_entry_n = 0; } } - if (I.sel_widget) { - selection_widget_up(RZ_MIN(I.sel_widget->h, RZ_SELWIDGET_MAXH)); - selection_widget_draw(); + if (line->sel_widget) { + selection_widget_up(line, RZ_MIN(line->sel_widget->h, RZ_SELWIDGET_MAXH)); + selection_widget_draw(line); } break; case '6': // pag down buf[1] = rz_cons_readchar(); - if (I.hud) { + if (line->hud) { rz_cons_get_size(&rows); - I.hud->top_entry_n += (rows - 1); - if (I.hud->top_entry_n >= I.hud->current_entry_n) { - I.hud->top_entry_n = I.hud->current_entry_n - 1; + line->hud->top_entry_n += (rows - 1); + if (line->hud->top_entry_n >= line->hud->current_entry_n) { + line->hud->top_entry_n = line->hud->current_entry_n - 1; } } - if (I.sel_widget) { - selection_widget_down(RZ_MIN(I.sel_widget->h, RZ_SELWIDGET_MAXH)); - selection_widget_draw(); + if (line->sel_widget) { + selection_widget_down(line, RZ_MIN(line->sel_widget->h, RZ_SELWIDGET_MAXH)); + selection_widget_draw(line); } break; case '9': // handle mouse wheel key = rz_cons_readchar(); cons->mouse_event = MOUSE_DEFAULT; if (key == '6') { // up - if (I.hud && I.hud->top_entry_n + 1 < I.hud->current_entry_n) { - I.hud->top_entry_n--; + if (line->hud && line->hud->top_entry_n + 1 < line->hud->current_entry_n) { + line->hud->top_entry_n--; } } else if (key == '7') { // down - if (I.hud && I.hud->top_entry_n >= 0) { - I.hud->top_entry_n++; + if (line->hud && line->hud->top_entry_n >= 0) { + line->hud->top_entry_n++; } } while (rz_cons_readchar() != 'M') { @@ -1934,56 +1948,56 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { break; /* arrows */ case 'A': // up arrow - if (I.hud) { - if (I.hud->top_entry_n > 0) { - I.hud->top_entry_n--; + if (line->hud) { + if (line->hud->top_entry_n > 0) { + line->hud->top_entry_n--; } - } else if (I.sel_widget) { - selection_widget_up(1); - selection_widget_draw(); + } else if (line->sel_widget) { + selection_widget_up(line, 1); + selection_widget_draw(line); } else if (gcomp) { gcomp_idx++; } else { - undo_reset(); - I.history.do_setup_match = o_do_setup_match; - if (rz_line_hist_up() == -1) { + undo_reset(line); + line->history.do_setup_match = o_do_setup_match; + if (rz_line_hist_up(line) == -1) { rz_cons_break_pop(); return NULL; } } break; case 'B': // down arrow - if (I.hud) { - if (I.hud->top_entry_n + 1 < I.hud->current_entry_n) { - I.hud->top_entry_n++; + if (line->hud) { + if (line->hud->top_entry_n + 1 < line->hud->current_entry_n) { + line->hud->top_entry_n++; } - } else if (I.sel_widget) { - selection_widget_down(1); - selection_widget_draw(); + } else if (line->sel_widget) { + selection_widget_down(line, 1); + selection_widget_draw(line); } else if (gcomp) { if (gcomp_idx > 0) { gcomp_idx--; } } else { - undo_reset(); - I.history.do_setup_match = o_do_setup_match; - if (rz_line_hist_down() == -1) { + undo_reset(line); + line->history.do_setup_match = o_do_setup_match; + if (rz_line_hist_down(line) == -1) { rz_cons_break_pop(); return NULL; } } break; case 'C': // right arrow - __move_cursor_right(); + __move_cursor_right(line); break; case 'D': // left arrow - __move_cursor_left(); + __move_cursor_left(line); break; case 0x31: // control + arrow ch = rz_cons_readchar(); if (ch == 0x7e) { // HOME in screen/tmux // corresponding END is 0x34 below (the 0x7e is ignored there) - I.buffer.index = 0; + line->buffer.index = 0; break; } rz_cons_readchar(); @@ -1992,39 +2006,39 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { switch (ch) { case 0x41: // first - I.buffer.index = 0; + line->buffer.index = 0; break; case 0x44: // previous word - for (i = I.buffer.index; i > 0; i--) { - if (I.buffer.data[i] == ' ') { - I.buffer.index = i - 1; + for (i = line->buffer.index; i > 0; i--) { + if (line->buffer.data[i] == ' ') { + line->buffer.index = i - 1; break; } } - if (I.buffer.data[i] != ' ') { - I.buffer.index = 0; + if (line->buffer.data[i] != ' ') { + line->buffer.index = 0; } break; case 0x42: // end - I.buffer.index = I.buffer.length; + line->buffer.index = line->buffer.length; break; case 0x43: // next word - for (i = I.buffer.index; i < I.buffer.length; i++) { - if (I.buffer.data[i] == ' ') { - I.buffer.index = i + 1; + for (i = line->buffer.index; i < line->buffer.length; i++) { + if (line->buffer.data[i] == ' ') { + line->buffer.index = i + 1; break; } } - if (I.buffer.data[i] != ' ') { - I.buffer.index = I.buffer.length; + if (line->buffer.data[i] != ' ') { + line->buffer.index = line->buffer.length; } break; default: - if (I.cb_fkey) { - I.cb_fkey(I.user, fkey); + if (line->cb_fkey) { + line->cb_fkey(line->user, fkey); } break; } @@ -2034,24 +2048,24 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { rz_cons_readchar(); /* fall through */ case 0x48: // HOME - if (I.sel_widget) { - selection_widget_up(I.sel_widget->options_len - 1); - selection_widget_draw(); + if (line->sel_widget) { + selection_widget_up(line, line->sel_widget->options_len - 1); + selection_widget_draw(line); break; } - I.buffer.index = 0; + line->buffer.index = 0; break; case 0x34: // END case 0x38: // END xrvt-unicode rz_cons_readchar(); /* fall through */ case 0x46: // END - if (I.sel_widget) { - selection_widget_down(I.sel_widget->options_len - 1); - selection_widget_draw(); + if (line->sel_widget) { + selection_widget_down(line, line->sel_widget->options_len - 1); + selection_widget_draw(line); break; } - I.buffer.index = I.buffer.length; + line->buffer.index = line->buffer.length; break; } } @@ -2059,43 +2073,43 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { break; case 8: case 127: - if (I.hud && (I.buffer.index == 0)) { - I.hud->activate = false; - I.hud->current_entry_n = -1; + if (line->hud && (line->buffer.index == 0)) { + line->hud->activate = false; + line->hud->current_entry_n = -1; } - __delete_prev_char(); + __delete_prev_char(line); break; case 9: // TAB tab - if (I.sel_widget) { - selection_widget_down(1); - I.sel_widget->complete_common = true; - selection_widget_draw(); - } - if (I.hud) { - if (I.hud->top_entry_n + 1 < I.hud->current_entry_n) { - I.hud->top_entry_n++; + if (line->sel_widget) { + selection_widget_down(line, 1); + line->sel_widget->complete_common = true; + selection_widget_draw(line); + } + if (line->hud) { + if (line->hud->top_entry_n + 1 < line->hud->current_entry_n) { + line->hud->top_entry_n++; } else { - I.hud->top_entry_n = 0; + line->hud->top_entry_n = 0; } } else { - rz_line_autocomplete(); + rz_line_autocomplete(line); rz_cons_flush(); } break; case 10: // ^J -- ignore case 13: // enter - if (I.hud) { - I.hud->activate = false; + if (line->hud) { + line->hud->activate = false; break; } - if (I.sel_widget) { - selection_widget_select(); + if (line->sel_widget) { + selection_widget_select(line); break; } - if (gcomp && I.buffer.length > 0) { - strncpy(I.buffer.data, gcomp_line, RZ_LINE_BUFSIZE - 1); - I.buffer.data[RZ_LINE_BUFSIZE - 1] = '\0'; - I.buffer.length = strlen(gcomp_line); + if (gcomp && line->buffer.length > 0) { + strncpy(line->buffer.data, gcomp_line, RZ_LINE_BUFSIZE - 1); + line->buffer.data[RZ_LINE_BUFSIZE - 1] = '\0'; + line->buffer.length = strlen(gcomp_line); } gcomp_idx = gcomp = 0; goto _end; @@ -2105,51 +2119,51 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { } { int size = utflen; - if (I.buffer.length + size >= RZ_LINE_BUFSIZE) { + if (line->buffer.length + size >= RZ_LINE_BUFSIZE) { break; } } - if (I.buffer.index < I.buffer.length) { - if ((I.buffer.length + utflen) < sizeof(I.buffer.data)) { - I.buffer.length += utflen; - for (i = I.buffer.length; i > I.buffer.index; i--) { - I.buffer.data[i] = I.buffer.data[i - utflen]; + if (line->buffer.index < line->buffer.length) { + if ((line->buffer.length + utflen) < sizeof(line->buffer.data)) { + line->buffer.length += utflen; + for (i = line->buffer.length; i > line->buffer.index; i--) { + line->buffer.data[i] = line->buffer.data[i - utflen]; } - memcpy(I.buffer.data + I.buffer.index, buf, utflen); - undo_add_entry(I.buffer.index, NULL, rz_str_ndup(buf, utflen)); + memcpy(line->buffer.data + line->buffer.index, buf, utflen); + undo_add_entry(line, line->buffer.index, NULL, rz_str_ndup(buf, utflen)); } } else { - if ((I.buffer.length + utflen) < sizeof(I.buffer.data)) { - memcpy(I.buffer.data + I.buffer.length, buf, utflen); - I.buffer.length += utflen; - if (!undo_concat_entry(buf, utflen)) { - undo_add_entry(I.buffer.index, NULL, rz_str_ndup(buf, utflen)); + if ((line->buffer.length + utflen) < sizeof(line->buffer.data)) { + memcpy(line->buffer.data + line->buffer.length, buf, utflen); + line->buffer.length += utflen; + if (!undo_concat_entry(line, buf, utflen)) { + undo_add_entry(line, line->buffer.index, NULL, rz_str_ndup(buf, utflen)); } } - I.buffer.data[I.buffer.length] = '\0'; + line->buffer.data[line->buffer.length] = '\0'; } - if ((I.buffer.index + utflen) <= I.buffer.length) { - I.buffer.index += utflen; + if ((line->buffer.index + utflen) <= line->buffer.length) { + line->buffer.index += utflen; } break; } - if (I.sel_widget && I.buffer.length != prev_buflen) { - prev_buflen = I.buffer.length; - rz_line_autocomplete(); + if (line->sel_widget && line->buffer.length != prev_buflen) { + prev_buflen = line->buffer.length; + rz_line_autocomplete(line); rz_cons_flush(); } prev = buf[0]; - if (I.echo) { + if (line->echo) { if (gcomp) { gcomp_line = ""; int counter = 0; - if (I.history.data != NULL) { - for (i = I.history.size - 1; i >= 0; i--) { - if (!I.history.data[i]) { + if (line->history.data != NULL) { + for (i = line->history.size - 1; i >= 0; i--) { + if (!line->history.data[i]) { continue; } - if (strstr(I.history.data[i], I.buffer.data)) { - gcomp_line = I.history.data[i]; + if (strstr(line->history.data[i], line->buffer.data)) { + gcomp_line = line->history.data[i]; if (++counter > gcomp_idx) { break; } @@ -2162,34 +2176,34 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { } } const char *prompt = gcomp_is_rev ? "reverse-i-search" : "forward-i-search"; - printf("\r (%s (%s)): %s\r", prompt, I.buffer.data, gcomp_line); + printf("\r (%s (%s)): %s\r", prompt, line->buffer.data, gcomp_line); } else { - __print_prompt(); + __print_prompt(line); } fflush(stdout); } enable_yank_pop = yank_flag ? 1 : 0; - if (I.hud) { + if (line->hud) { goto _end; } } _end: - undo_reset(); + undo_reset(line); rz_cons_break_pop(); rz_cons_set_raw(0); rz_cons_enable_mouse(mouse_status); - if (I.echo) { - printf("\r%s%s\n", I.prompt, I.buffer.data); + if (line->echo) { + printf("\r%s%s\n", line->prompt, line->buffer.data); fflush(stdout); } - RZ_FREE(I.sel_widget); + RZ_FREE(line->sel_widget); // should be here or not? - if (!memcmp(I.buffer.data, "!history", 8)) { - // if (I.buffer.data[0]=='!' && I.buffer.data[1]=='\0') { - rz_line_hist_list(); + if (!memcmp(line->buffer.data, "!history", 8)) { + // if (line->buffer.data[0]=='!' && line->buffer.data[1]=='\0') { + rz_line_hist_list(line); return rz_line_nullstr; } - return I.buffer.data[0] != '\0' ? I.buffer.data : rz_line_nullstr; + return line->buffer.data[0] != '\0' ? line->buffer.data : rz_line_nullstr; } diff --git a/librz/cons/hud.c b/librz/cons/hud.c index cc671bf501d..d3f6a7da2c3 100644 --- a/librz/cons/hud.c +++ b/librz/cons/hud.c @@ -252,7 +252,7 @@ RZ_API char *rz_cons_hud(RzList /**/ *list, const char *prompt) { rz_list_free(filtered_list); #endif rz_cons_visual_flush(); - (void)rz_line_readline(); + (void)rz_line_readline(I(line)); rz_str_ncpy(user_input, I(line)->buffer.data, HUD_BUF_SIZE); // to search if (!hud->activate) { diff --git a/librz/cons/input.c b/librz/cons/input.c index 82a9b6a5410..9288b2a1ffd 100644 --- a/librz/cons/input.c +++ b/librz/cons/input.c @@ -690,19 +690,19 @@ RZ_API bool rz_cons_yesno(int def, const char *fmt, ...) { } RZ_API char *rz_cons_input(const char *msg) { - char *oprompt = rz_line_get_prompt(); + char *oprompt = rz_line_get_prompt(I->line); if (!oprompt) { return NULL; } char buf[1024]; if (msg) { - rz_line_set_prompt(msg); + rz_line_set_prompt(I->line, msg); } else { - rz_line_set_prompt(""); + rz_line_set_prompt(I->line, ""); } buf[0] = 0; rz_cons_fgets(buf, sizeof(buf), 0, NULL); - rz_line_set_prompt(oprompt); + rz_line_set_prompt(I->line, oprompt); free(oprompt); return strdup(buf); } diff --git a/librz/cons/less.c b/librz/cons/less.c index 907b4a75954..1127d8def5f 100644 --- a/librz/cons/less.c +++ b/librz/cons/less.c @@ -7,6 +7,8 @@ #include #include "pager_private.h" +#define I(x) rz_cons_singleton()->x + RZ_API int rz_cons_less_str(const char *str, const char *exitkeys) { rz_return_val_if_fail(str && *str, 0); if (!rz_cons_is_interactive()) { @@ -119,8 +121,8 @@ RZ_API int rz_cons_less_str(const char *str, const char *exitkeys) { break; case '/': /* search */ rz_cons_reset_colors(); - rz_line_set_prompt("/"); - sreg = rz_line_readline(); + rz_line_set_prompt(I(line), "/"); + sreg = rz_line_readline(I(line)); from = RZ_MIN(lines_count - 1, from); /* repeat last search if empty string is provided */ if (sreg[0]) { /* prepare for a new search */ diff --git a/librz/cons/line.c b/librz/cons/line.c index 9792eb2ed3a..9fbcd22c642 100644 --- a/librz/cons/line.c +++ b/librz/cons/line.c @@ -4,73 +4,74 @@ #include #include -static RzLine rz_line_instance; -#define I rz_line_instance - static void rz_line_nscompletion_init(RzLineNSCompletion *c) { c->run = NULL; c->run_user = NULL; } -static void undo_free(void) { - rz_vector_free(I.undo_vec); - I.undo_vec = NULL; - I.undo_cursor = 0; - I.undo_continue = false; -} - -RZ_API RzLine *rz_line_singleton(void) { - return &rz_line_instance; +static void undo_free(RzLine *line) { + if (!line) { + return; + } + rz_vector_free(line->undo_vec); + line->undo_vec = NULL; + line->undo_cursor = 0; + line->undo_continue = false; } -RZ_API RzLine *rz_line_new(void) { - I.hist_up = NULL; - I.hist_down = NULL; - I.prompt = strdup("> "); - I.contents = NULL; - I.enable_vi_mode = false; - I.clipboard = NULL; - I.kill_ring = rz_list_newf(free); - I.kill_ring_ptr = -1; +RZ_API RZ_OWN RzLine *rz_line_new(void) { + RzLine *line = RZ_NEW0(RzLine); + if (!line) { + return NULL; + } + line->prompt = strdup("> "); + line->kill_ring = rz_list_newf(free); + line->kill_ring_ptr = -1; #if __WINDOWS__ - I.vtmode = rz_cons_detect_vt_mode(); + line->vtmode = rz_cons_detect_vt_mode(); #else - I.vtmode = RZ_VIRT_TERM_MODE_COMPLETE; + line->vtmode = RZ_VIRT_TERM_MODE_COMPLETE; #endif - if (!rz_line_dietline_init()) { - eprintf("error: rz_line_dietline_init\n"); + if (!rz_line_dietline_init(line)) { + RZ_LOG_ERROR("error: rz_line_dietline_init\n"); } - rz_line_completion_init(&I.completion, 4096); - rz_line_nscompletion_init(&I.ns_completion); - return &I; + rz_line_completion_init(&line->completion, 4096); + rz_line_nscompletion_init(&line->ns_completion); + return line; } -RZ_API void rz_line_free(void) { - // XXX: prompt out of the heap? - free((void *)I.prompt); - I.prompt = NULL; - rz_list_free(I.kill_ring); - rz_line_hist_free(); - undo_free(); - rz_line_completion_fini(&I.completion); +RZ_API void rz_line_free(RZ_NULLABLE RzLine *line) { + if (!line) { + return; + } + free((void *)line->prompt); + line->prompt = NULL; + rz_list_free(line->kill_ring); + rz_line_hist_free(line); + undo_free(line); + rz_line_completion_fini(&line->completion); + free(line); } -RZ_API void rz_line_clipboard_push(const char *str) { - I.kill_ring_ptr += 1; - rz_list_insert(I.kill_ring, I.kill_ring_ptr, strdup(str)); +RZ_API void rz_line_clipboard_push(RZ_NONNULL RzLine *line, RZ_NONNULL const char *str) { + rz_return_if_fail(line && str); + line->kill_ring_ptr += 1; + rz_list_insert(line->kill_ring, line->kill_ring_ptr, strdup(str)); } // handle const or dynamic prompts? -RZ_API void rz_line_set_prompt(const char *prompt) { - free(I.prompt); - I.prompt = strdup(prompt); +RZ_API void rz_line_set_prompt(RZ_NONNULL RzLine *line, RZ_NONNULL const char *prompt) { + rz_return_if_fail(line && prompt); + free(line->prompt); + line->prompt = strdup(prompt); RzCons *cons = rz_cons_singleton(); - I.cb_fkey = cons->cb_fkey; + line->cb_fkey = cons->cb_fkey; } // handle const or dynamic prompts? -RZ_API RZ_OWN char *rz_line_get_prompt(void) { - return strdup(I.prompt); +RZ_API RZ_OWN char *rz_line_get_prompt(RZ_NONNULL RzLine *line) { + rz_return_val_if_fail(line, NULL); + return strdup(line->prompt); } RZ_API void rz_line_completion_init(RzLineCompletion *completion, size_t args_limit) { diff --git a/librz/cons/prompt.c b/librz/cons/prompt.c index 0bd05edc115..1d6ed7feba9 100644 --- a/librz/cons/prompt.c +++ b/librz/cons/prompt.c @@ -23,7 +23,7 @@ RZ_API RZ_OWN char *rz_cons_prompt(RZ_NONNULL const char *str, RZ_NULLABLE const RZ_FREE(rz_cons_singleton()->line->contents); } *cmd = '\0'; - rz_line_set_prompt(str); + rz_line_set_prompt(rz_cons_singleton()->line, str); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { *cmd = '\0'; } @@ -31,7 +31,7 @@ RZ_API RZ_OWN char *rz_cons_prompt(RZ_NONNULL const char *str, RZ_NULLABLE const if (*cmd) { res = strdup(cmd); } - rz_line_set_prompt(oprompt); + rz_line_set_prompt(rz_cons_singleton()->line, oprompt); free(oprompt); RZ_FREE(rz_cons_singleton()->line->contents); return res; diff --git a/librz/core/agraph.c b/librz/core/agraph.c index 8be6f287095..7894d6e5ff2 100644 --- a/librz/core/agraph.c +++ b/librz/core/agraph.c @@ -3949,12 +3949,13 @@ RZ_API RzAGraph *rz_agraph_new(RzConsCanvas *can) { static void visual_offset(RzAGraph *g, RzCore *core) { char buf[256]; int rows; + RzLine *line = core->cons->line; rz_cons_get_size(&rows); rz_cons_gotoxy(0, rows); rz_cons_flush(); - core->cons->line->prompt_type = RZ_LINE_PROMPT_OFFSET; - rz_line_set_hist_callback(core->cons->line, &rz_line_hist_offset_up, &rz_line_hist_offset_down); - rz_line_set_prompt("[offset]> "); + line->prompt_type = RZ_LINE_PROMPT_OFFSET; + rz_line_set_hist_callback(line, &rz_line_hist_offset_up, &rz_line_hist_offset_down); + rz_line_set_prompt(line, "[offset]> "); strcpy(buf, "s "); if (rz_cons_fgets(buf + 2, sizeof(buf) - 2, 0, NULL) > 0) { if (buf[2] == '.') { @@ -3963,7 +3964,7 @@ static void visual_offset(RzAGraph *g, RzCore *core) { rz_core_cmd0(core, buf); rz_line_set_hist_callback(core->cons->line, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); } - core->cons->line->prompt_type = RZ_LINE_PROMPT_DEFAULT; + line->prompt_type = RZ_LINE_PROMPT_DEFAULT; } static void goto_asmqjmps(RzAGraph *g, RzCore *core) { @@ -4141,6 +4142,7 @@ RZ_IPI int rz_core_visual_graph(RzCore *core, RzAGraph *g, RzAnalysisFunction *_ const char *key_s; RzConsCanvas *can, *o_can = NULL; RzCoreVisual *visual = core->visual; + RzLine *line = core->cons->line; bool graph_allocated = false; int movspeed; int ret, invscroll; @@ -4281,10 +4283,10 @@ RZ_IPI int rz_core_visual_graph(RzCore *core, RzAGraph *g, RzAnalysisFunction *_ case '=': { // TODO: edit showcursor(core, true); const char *cmd = rz_config_get(core->config, "cmd.gprompt"); - rz_line_set_prompt("cmd.gprompt> "); - core->cons->line->contents = strdup(cmd); - const char *buf = rz_line_readline(); - core->cons->line->contents = NULL; + rz_line_set_prompt(line, "cmd.gprompt> "); + line->contents = strdup(cmd); + const char *buf = rz_line_readline(line); + line->contents = NULL; rz_config_set(core->config, "cmd.gprompt", buf); showcursor(core, false); } break; @@ -4581,7 +4583,7 @@ RZ_IPI int rz_core_visual_graph(RzCore *core, RzAGraph *g, RzAnalysisFunction *_ if (fcn) { showcursor(core, true); char buf[256]; - rz_line_set_prompt("[comment]> "); + rz_line_set_prompt(line, "[comment]> "); if (rz_cons_fgets(buf, sizeof(buf), 0, NULL) > 0) { rz_meta_set_string(core->analysis, RZ_META_TYPE_COMMENT, core->offset, buf); } diff --git a/librz/core/cconfig.c b/librz/core/cconfig.c index c2f6dce940f..8ed82de06d1 100644 --- a/librz/core/cconfig.c +++ b/librz/core/cconfig.c @@ -2152,17 +2152,18 @@ static bool scr_vtmode(void *user, void *data) { node->i_value = RZ_VIRT_TERM_MODE_OUTPUT_ONLY; } node->i_value = node->i_value > RZ_VIRT_TERM_MODE_COMPLETE ? RZ_VIRT_TERM_MODE_COMPLETE : node->i_value; - rz_line_singleton()->vtmode = rz_cons_singleton()->vtmode = node->i_value; + RzCons *cons = rz_cons_singleton(); + cons->line->vtmode = cons->vtmode = node->i_value; DWORD mode; HANDLE input = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(input, &mode); if (node->i_value == RZ_VIRT_TERM_MODE_COMPLETE) { SetConsoleMode(input, mode & ENABLE_VIRTUAL_TERMINAL_INPUT); - rz_cons_singleton()->term_raw |= ENABLE_VIRTUAL_TERMINAL_INPUT; + cons->term_raw |= ENABLE_VIRTUAL_TERMINAL_INPUT; } else { SetConsoleMode(input, mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT); - rz_cons_singleton()->term_raw &= ~ENABLE_VIRTUAL_TERMINAL_INPUT; + cons->term_raw &= ~ENABLE_VIRTUAL_TERMINAL_INPUT; } HANDLE streams[] = { GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE) }; int i; @@ -2296,14 +2297,15 @@ static bool cb_scrprompt(void *user, void *data) { RzCore *core = (RzCore *)user; RzConfigNode *node = (RzConfigNode *)data; core->print->scr_prompt = node->i_value; - rz_line_singleton()->echo = node->i_value; + core->cons->line->echo = node->i_value; return true; } static bool cb_scrrows(void *user, void *data) { + RzCore *core = (RzCore *)user; RzConfigNode *node = (RzConfigNode *)data; int n = atoi(node->value); - ((RzCore *)user)->cons->force_rows = n; + core->cons->force_rows = n; return true; } diff --git a/librz/core/cmd/cmd.c b/librz/core/cmd/cmd.c index 8d13b3c62ca..a0c6c8fd007 100644 --- a/librz/core/cmd/cmd.c +++ b/librz/core/cmd/cmd.c @@ -744,7 +744,7 @@ RZ_IPI int rz_cmd_kuery(void *data, const char *input) { RzList *sdb_hist = line->sdbshell_hist; rz_line_set_hist_callback(line, &rz_line_hist_sdb_up, &rz_line_hist_sdb_down); for (;;) { - rz_line_set_prompt(p); + rz_line_set_prompt(line, p); if (rz_cons_fgets(buf, sizeof(buf), 0, NULL) < 1) { break; } @@ -5344,6 +5344,7 @@ static RzCmdStatus core_cmd_tsrzcmd(RzCore *core, const char *cstr, bool split_l } TSNode root = ts_tree_root_node(tree); + RzLine *line = core->cons->line; RzCmdStatus res = RZ_CMD_STATUS_INVALID; struct tsr2cmd_state state; @@ -5357,7 +5358,7 @@ static RzCmdStatus core_cmd_tsrzcmd(RzCore *core, const char *cstr, bool split_l rz_pvector_init(&state.saved_tree, NULL); if (state.log) { - rz_line_hist_add(state.input); + rz_line_hist_add(line, state.input); } char *ts_str = ts_node_string(root); diff --git a/librz/core/cmd/cmd_history.c b/librz/core/cmd/cmd_history.c index c054f0afcc2..a63859c5bc3 100644 --- a/librz/core/cmd/cmd_history.c +++ b/librz/core/cmd/cmd_history.c @@ -9,7 +9,7 @@ RZ_IPI RzCmdStatus rz_history_list_or_exec_handler(RzCore *core, int argc, const char **argv) { if (argc == 1) { - rz_line_hist_list(); + rz_line_hist_list(core->cons->line); return RZ_CMD_STATUS_OK; } @@ -19,7 +19,7 @@ RZ_IPI RzCmdStatus rz_history_list_or_exec_handler(RzCore *core, int argc, const return RZ_CMD_STATUS_ERROR; } - const char *cmd = rz_line_hist_get(index); + const char *cmd = rz_line_hist_get(core->cons->line, index); if (!cmd) { RZ_LOG_ERROR("cannot find command with index %d.\n", index); return RZ_CMD_STATUS_ERROR; @@ -30,13 +30,13 @@ RZ_IPI RzCmdStatus rz_history_list_or_exec_handler(RzCore *core, int argc, const } RZ_IPI RzCmdStatus rz_history_clear_handler(RzCore *core, int argc, const char **argv) { - rz_line_hist_free(); + rz_line_hist_free(core->cons->line); return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_history_save_handler(RzCore *core, int argc, const char **argv) { char *history = rz_path_home_history(); - rz_line_hist_save(history); + rz_line_hist_save(core->cons->line, history); free(history); return RZ_CMD_STATUS_OK; } diff --git a/librz/core/cmd/cmd_math.c b/librz/core/cmd/cmd_math.c index afc2e8278b7..0d35fe3f0c7 100644 --- a/librz/core/cmd/cmd_math.c +++ b/librz/core/cmd/cmd_math.c @@ -584,7 +584,7 @@ static bool get_prompt(RzCore *core, char *prompt, char *output, size_t output_s return false; } rz_cons_flush(); - rz_line_set_prompt(prompt); + rz_line_set_prompt(rz_cons_singleton()->line, prompt); rz_cons_fgets(output, output_sz, 0, NULL); output[output_sz - 1] = 0; return true; diff --git a/librz/core/cmd/cmd_print.c b/librz/core/cmd/cmd_print.c index d2aa7d13ccf..1ec363a54d2 100644 --- a/librz/core/cmd/cmd_print.c +++ b/librz/core/cmd/cmd_print.c @@ -7032,7 +7032,7 @@ RZ_IPI RzCmdStatus rz_cmd_print_raw_handler(RzCore *core, int argc, const char * } RZ_IPI RzCmdStatus rz_cmd_print_raw_colors_handler(RzCore *core, int argc, const char **argv) { - int len = argc > 1 ? rz_num_math(core->num, argv[1]) : strlen((const char *)core->block); + int len = argc > 1 ? rz_num_math(core->num, argv[1]) : core->blocksize; if (len < 0) { return RZ_CMD_STATUS_ERROR; } diff --git a/librz/core/core.c b/librz/core/core.c index 613b4606a17..3a431ba63c1 100644 --- a/librz/core/core.c +++ b/librz/core/core.c @@ -1660,7 +1660,7 @@ static RzLineNSCompletionResult *rzshell_autocomplete(RzLineBuffer *buf, RzLineP RZ_API int rz_core_fgets(char *buf, int len, void *user) { RzCore *core = (RzCore *)user; - RzCons *cons = rz_cons_singleton(); + RzCons *cons = core->cons; RzLine *rzline = cons->line; bool prompt = cons->context->is_interactive; buf[0] = '\0'; @@ -1674,7 +1674,7 @@ RZ_API int rz_core_fgets(char *buf, int len, void *user) { rzline->completion.run = NULL; rzline->completion.run_user = NULL; } - const char *ptr = rz_line_readline(); + const char *ptr = rz_line_readline(rzline); if (!ptr) { return -1; } @@ -2399,7 +2399,7 @@ RZ_API bool rz_core_init(RzCore *core) { core->cons->user_fgets_user = core; #endif char *history = rz_path_home_history(); - rz_line_hist_load(history); + rz_line_hist_load(core->cons->line, history); free(history); } core->print->cons = core->cons; @@ -2707,6 +2707,7 @@ static bool prompt_add_offset(RzCore *core, RzStrBuf *sb, bool add_sep) { } static void set_prompt(RzCore *r) { + RzLine *line = r->cons->line; const char *cmdprompt = rz_config_get(r->config, "cmd.prompt"); const char *BEGIN = ""; const char *END = ""; @@ -2737,7 +2738,7 @@ static void set_prompt(RzCore *r) { rz_strbuf_appendf(&prompt_ct, "]>%s ", END); char *prompt = rz_strbuf_drain_nofree(&prompt_ct); - rz_line_set_prompt(prompt); + rz_line_set_prompt(line, prompt); free(prompt); } diff --git a/librz/core/rtr_shell.c b/librz/core/rtr_shell.c index 7939dc078a3..9b1eadb2ffd 100644 --- a/librz/core/rtr_shell.c +++ b/librz/core/rtr_shell.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only static bool rtr_visual(RzCore *core, TextLog T, const char *cmd) { + RzLine *line = core->cons->line; bool autorefresh = false; if (cmd) { rz_cons_break_push(NULL, NULL); @@ -78,9 +79,9 @@ static bool rtr_visual(RzCore *core, TextLog T, const char *cmd) { #endif char buf[1024]; if (COLORFLAGS) { - rz_line_set_prompt(Color_RESET ":> "); + rz_line_set_prompt(line, Color_RESET ":> "); } else { - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); } showcursor(core, true); rz_cons_fgets(buf + 3, sizeof(buf) - 3, 0, NULL); @@ -109,14 +110,14 @@ static bool rtr_visual(RzCore *core, TextLog T, const char *cmd) { do { char buf[1024]; #if __UNIX__ - rz_line_set_prompt(Color_RESET ":> "); + rz_line_set_prompt(line, Color_RESET ":> "); #else - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); #endif showcursor(core, true); rz_cons_fgets(buf, sizeof(buf), 0, NULL); if (*buf) { - rz_line_hist_add(buf); + rz_line_hist_add(line, buf); char *res = rtrcmd(T, buf); if (res) { rz_cons_println(res); @@ -188,14 +189,15 @@ static void __rtr_shell(RzCore *core, int nth) { int len; const char *res; RzSocket *s = NULL; + RzLine *line = core->cons->line; TextLog T = { host, port, file }; snprintf(prompt, sizeof(prompt), "[%s://%s:%s/%s]> ", proto, host, port, file); snprintf(prompt2, sizeof(prompt2), "[%s:%s]$ ", host, port); for (;;) { - rz_line_set_prompt(prompt); - res = rz_line_readline(); + rz_line_set_prompt(line, prompt); + res = rz_line_readline(line); if (!res || !*res) { break; } @@ -204,8 +206,8 @@ static void __rtr_shell(RzCore *core, int nth) { } if (!strcmp(res, "!sh")) { for (;;) { - rz_line_set_prompt(prompt2); - res = rz_line_readline(); + rz_line_set_prompt(line, prompt2); + res = rz_line_readline(line); if (!res || !*res || !strcmp(res, "exit")) { break; } @@ -221,7 +223,7 @@ static void __rtr_shell(RzCore *core, int nth) { res = res ? res + 2 : str; const char *tail = (res[strlen(res) - 1] == '\n') ? "" : "\n"; printf("%s%s", res, tail); - rz_line_hist_add(str); + rz_line_hist_add(line, str); free(str); } free(ptr); @@ -237,7 +239,7 @@ static void __rtr_shell(RzCore *core, int nth) { char *cmdline = rz_str_newf("%d %s", nth, res); rz_core_rtr_cmd(core, cmdline); rz_cons_flush(); - rz_line_hist_add(res); + rz_line_hist_add(line, res); } } rz_socket_free(s); diff --git a/librz/core/tui/biteditor.c b/librz/core/tui/biteditor.c index 33d3fc637de..4daacdb485e 100644 --- a/librz/core/tui/biteditor.c +++ b/librz/core/tui/biteditor.c @@ -28,6 +28,7 @@ RZ_IPI bool rz_core_visual_bit_editor(RzCore *core) { RzAnalysisOp aop; ut8 buf[sizeof(ut64)]; bool bitsInLine = false; + RzLine *rzline = core->cons->line; if (core->blocksize < sizeof(ut64)) { return false; @@ -212,8 +213,8 @@ RZ_IPI bool rz_core_visual_bit_editor(RzCore *core) { buf[x / 8] = rotate_nibble(buf[(x / 8)], 1); break; case 'i': { - rz_line_set_prompt("> "); - const char *line = rz_line_readline(); + rz_line_set_prompt(rzline, "> "); + const char *line = rz_line_readline(rzline); ut64 num = rz_num_math(core->num, line); if (num || (!num && *line == '0')) { buf[x / 8] = num; @@ -263,7 +264,7 @@ RZ_IPI bool rz_core_visual_bit_editor(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); cmd[0] = '\0'; - rz_line_set_prompt(":> "); + rz_line_set_prompt(rzline, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } diff --git a/librz/core/tui/classes.c b/librz/core/tui/classes.c index 237d0f11d29..cbb3ead7969 100644 --- a/librz/core/tui/classes.c +++ b/librz/core/tui/classes.c @@ -202,6 +202,7 @@ RZ_IPI int rz_core_visual_classes(RzCore *core) { int oldcur = 0; char *grep = NULL; bool grepmode = false; + RzLine *line = core->cons->line; RzBinObject *bin_obj = rz_bin_cur_object(core->bin); const RzPVector *vec = rz_bin_object_get_classes(bin_obj); if (!vec || rz_pvector_empty(vec)) { @@ -368,7 +369,7 @@ RZ_IPI int rz_core_visual_classes(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); cmd[0] = '\0'; - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } @@ -490,6 +491,7 @@ RZ_IPI int rz_core_visual_analysis_classes(RzCore *core) { int oldcur = 0; char mode = ' '; const char *class_name = ""; + RzLine *line = core->cons->line; if (rz_list_empty(list)) { rz_cons_message("No Classes"); @@ -577,7 +579,7 @@ RZ_IPI int rz_core_visual_analysis_classes(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); command[0] = '\0'; - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); if (rz_cons_fgets(command, sizeof(command), 0, NULL) < 0) { command[0] = '\0'; } diff --git a/librz/core/tui/colors.c b/librz/core/tui/colors.c index bdebeda412b..84f0013695d 100644 --- a/librz/core/tui/colors.c +++ b/librz/core/tui/colors.c @@ -15,7 +15,8 @@ RZ_IPI void rz_core_visual_colors(RzCore *core) { char *color = calloc(1, 64), cstr[32]; char preview_cmd[128] = "pd $r"; int ch, opt = 0, oopt = -1; - bool truecolor = rz_cons_singleton()->context->color_mode == COLOR_MODE_16M; + RzCons *cons = rz_cons_singleton(); + bool truecolor = cons->context->color_mode == COLOR_MODE_16M; char *rgb_xxx_fmt = truecolor ? "rgb:%2.2x%2.2x%2.2x " : "rgb:%x%x%x "; const char *k; RzColor rcolor; @@ -133,7 +134,7 @@ RZ_IPI void rz_core_visual_colors(RzCore *core) { rcolor.b = rz_num_rand32(0xff); break; case 'c': - rz_line_set_prompt("Preview command> "); + rz_line_set_prompt(cons->line, "Preview command> "); rz_cons_show_cursor(true); rz_cons_fgets(preview_cmd, sizeof(preview_cmd), 0, NULL); rz_cons_show_cursor(false); diff --git a/librz/core/tui/config.c b/librz/core/tui/config.c index f25bd38ff82..8b585b72a76 100644 --- a/librz/core/tui/config.c +++ b/librz/core/tui/config.c @@ -25,6 +25,7 @@ static void config_visual_hit_i(RzCore *core, const char *name, int delta) { static void config_visual_hit(RzCore *core, const char *name, int editor) { char buf[1024]; RzConfigNode *node; + RzLine *line = core->cons->line; if (!(node = rz_config_node_get(core->config, name))) { return; @@ -43,7 +44,7 @@ static void config_visual_hit(RzCore *core, const char *name, int editor) { rz_cons_show_cursor(true); rz_cons_flush(); rz_cons_set_raw(0); - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); rz_cons_fgets(buf, sizeof(buf), 0, 0); rz_cons_set_raw(1); rz_cons_show_cursor(false); diff --git a/librz/core/tui/define.c b/librz/core/tui/define.c index 2627d061994..d23c1a6ce3d 100644 --- a/librz/core/tui/define.c +++ b/librz/core/tui/define.c @@ -43,8 +43,9 @@ static void handleHints(RzCore *core) { rz_cons_fill_line(); rz_cons_printf("\r%s\n", lines[i]); } + RzLine *line = core->cons->line; rz_cons_flush(); - rz_line_set_prompt("analysis hint: "); + rz_line_set_prompt(line, "analysis hint: "); if (rz_cons_fgets(ch, sizeof(ch), 0, NULL) > 0) { switch (ch[0]) { case 'b': { @@ -63,6 +64,7 @@ static void handleHints(RzCore *core) { RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) { RzCoreVisual *visual = core->visual; + RzLine *line = core->cons->line; int plen = core->blocksize; ut64 off = core->offset; int i, h = 0, n, ch, ntotal = 0; @@ -116,7 +118,7 @@ RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) rz_cons_show_cursor(true); rz_core_cmd0(core, "pf?"); rz_cons_flush(); - rz_line_set_prompt("format: "); + rz_line_set_prompt(line, "format: "); strcpy(cmd, "Cf 0 "); if (rz_cons_fgets(cmd + 5, sizeof(cmd) - 5, 0, NULL) > 0) { rz_core_cmdf(core, "%s @ 0x%08" PFMT64x, cmd, off); @@ -131,7 +133,7 @@ RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) case 'o': { char str[128]; rz_cons_show_cursor(true); - rz_line_set_prompt(ch == 't' ? "type: " : "opstr: "); + rz_line_set_prompt(line, ch == 't' ? "type: " : "opstr: "); if (rz_cons_fgets(str, sizeof(str), 0, NULL) > 0) { rz_core_cmdf(core, "ah%c %s @ 0x%" PFMT64x, ch, str, off); } @@ -142,7 +144,7 @@ RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) case 'i': { char str[128]; rz_cons_show_cursor(true); - rz_line_set_prompt("immbase: "); + rz_line_set_prompt(line, "immbase: "); if (rz_cons_fgets(str, sizeof(str), 0, NULL) > 0) { int base = rz_num_base_of_string(core->num, str); rz_analysis_hint_set_immbase(core->analysis, off, base); @@ -151,7 +153,7 @@ RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) case 'I': { char str[128]; rz_cons_show_cursor(true); - rz_line_set_prompt("immbase: "); + rz_line_set_prompt(line, "immbase: "); if (rz_cons_fgets(str, sizeof(str), 0, NULL) > 0) { rz_core_cmdf(core, "ahi1 %s @ 0x%" PFMT64x, str, off); } @@ -266,7 +268,7 @@ RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) char cmd[128]; rz_cons_show_cursor(true); rz_cons_flush(); - rz_line_set_prompt("color: "); + rz_line_set_prompt(line, "color: "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) > 0) { rz_flag_item_set_color(item, cmd); rz_cons_set_raw(1); @@ -284,7 +286,7 @@ RZ_IPI void rz_core_visual_define(RzCore *core, const char *args, int distance) rz_cons_printf("Current flag size is: %" PFMT64d "\n", item->size); rz_cons_show_cursor(true); rz_cons_flush(); - rz_line_set_prompt("new size: "); + rz_line_set_prompt(line, "new size: "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) > 0) { item->size = rz_num_math(core->num, cmd); rz_cons_set_raw(1); diff --git a/librz/core/tui/esil.c b/librz/core/tui/esil.c index 3c3aa8a0acc..4fcb8bb90a3 100644 --- a/librz/core/tui/esil.c +++ b/librz/core/tui/esil.c @@ -43,6 +43,7 @@ RZ_IPI bool rz_core_visual_esil(RzCore *core) { RzAnalysisOp aop; ut8 buf[sizeof(ut64)]; unsigned int addrsize = rz_config_get_i(core->config, "esil.addr.size"); + RzLine *line = core->cons->line; if (core->blocksize < sizeof(ut64)) { return false; @@ -160,7 +161,7 @@ RZ_IPI bool rz_core_visual_esil(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); *cmd = 0; - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } diff --git a/librz/core/tui/flags.c b/librz/core/tui/flags.c index d352c7b3150..361d7f5ca11 100644 --- a/librz/core/tui/flags.c +++ b/librz/core/tui/flags.c @@ -62,6 +62,7 @@ RZ_IPI int rz_core_visual_trackflags(RzCore *core) { int menu = 0; int sort = SORT_NONE; RzCoreVisual *visual = core->visual; + RzLine *rzline = core->cons->line; if (rz_flag_space_is_empty(core->flags)) { menu = 1; @@ -214,7 +215,7 @@ RZ_IPI int rz_core_visual_trackflags(RzCore *core) { switch (menu) { case 0: // new flag space rz_cons_show_cursor(true); - rz_line_set_prompt("add flagspace: "); + rz_line_set_prompt(rzline, "add flagspace: "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) > 0) { rz_flag_space_set(core->flags, cmd); rz_cons_set_raw(1); @@ -223,7 +224,7 @@ RZ_IPI int rz_core_visual_trackflags(RzCore *core) { break; case 1: // new flag rz_cons_show_cursor(true); - rz_line_set_prompt("add flag: "); + rz_line_set_prompt(rzline, "add flag: "); strcpy(cmd, "f "); if (rz_cons_fgets(cmd + 2, sizeof(cmd) - 2, 0, NULL) > 0) { rz_core_cmd(core, cmd, 0); @@ -270,7 +271,7 @@ RZ_IPI int rz_core_visual_trackflags(RzCore *core) { snprintf(cmd, sizeof(cmd), "fr %s ", fs2); len = strlen(cmd); eprintf("Rename flag '%s' as:\n", fs2); - rz_line_set_prompt(":> "); + rz_line_set_prompt(rzline, ":> "); if (rz_cons_fgets(cmd + len, sizeof(cmd) - len, 0, NULL) < 0) { cmd[0] = '\0'; } @@ -285,7 +286,7 @@ RZ_IPI int rz_core_visual_trackflags(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); eprintf("Rename function '%s' as:\n", fs2); - rz_line_set_prompt(":> "); + rz_line_set_prompt(rzline, ":> "); if (rz_cons_fgets(line, sizeof(line), 0, NULL) < 0) { cmd[0] = '\0'; } @@ -341,7 +342,7 @@ RZ_IPI int rz_core_visual_trackflags(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); *cmd = 0; - rz_line_set_prompt(":> "); + rz_line_set_prompt(rzline, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { *cmd = 0; } diff --git a/librz/core/tui/hud.c b/librz/core/tui/hud.c index 9430b775c87..aa485f4a18c 100644 --- a/librz/core/tui/hud.c +++ b/librz/core/tui/hud.c @@ -164,7 +164,7 @@ RZ_IPI bool rz_core_visual_config_hud(RzCore *core) { rz_cons_set_raw(false); cmd[0] = '\0'; eprintf("Set new value for %s (old=%s)\n", res, oldvalue); - rz_line_set_prompt(":> "); + rz_line_set_prompt(core->cons->line, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } diff --git a/librz/core/tui/panels.c b/librz/core/tui/panels.c index 3a3f39f25e7..c6d666b7cbb 100644 --- a/librz/core/tui/panels.c +++ b/librz/core/tui/panels.c @@ -162,7 +162,7 @@ static const char *menus_settings_screen[] = { static const char *menus_Help[] = { "Toggle Help", - "License", "Version", + "Version", "Fortune", NULL }; @@ -509,7 +509,6 @@ static int __watch_points_cb(void *user); static int __references_cb(void *user); static int __help_cb(void *user); static int __fortune_cb(void *user); -static int __license_cb(void *user); static int __version_cb(void *user); static int __quit_cb(void *user); static int __io_cache_on_cb(void *user); @@ -1640,7 +1639,7 @@ void __handleComment(RzCore *core) { } char buf[4095]; int i; - rz_line_set_prompt("[Comment]> "); + rz_line_set_prompt(core->cons->line, "[Comment]> "); strcpy(buf, "\"CC "); i = strlen(buf); if (rz_cons_fgets(buf + i, sizeof(buf) - i, 0, NULL) > 0) { @@ -3638,11 +3637,6 @@ int __help_cb(void *user) { return 0; } -int __license_cb(void *user) { - rz_cons_message("Copyright 2006-2020 - pancake - LGPL"); - return 0; -} - int __version_cb(void *user) { char *v = rz_version_str(NULL); rz_cons_message(v); @@ -4572,9 +4566,7 @@ bool __init_panels_menu(RzCore *core) { parent = "Help"; i = 0; while (menus_Help[i]) { - if (!strcmp(menus_Help[i], "License")) { - __add_menu(core, parent, menus_Help[i], __license_cb); - } else if (!strcmp(menus_Help[i], "Version")) { + if (!strcmp(menus_Help[i], "Version")) { __add_menu(core, parent, menus_Help[i], __version_cb); } else if (!strcmp(menus_Help[i], "Fortune")) { __add_menu(core, parent, menus_Help[i], __fortune_cb); @@ -6324,7 +6316,7 @@ void __handle_tab_new_with_cur_panel(RzCore *core) { } void __panel_prompt(const char *prompt, char *buf, int len) { - rz_line_set_prompt(prompt); + rz_line_set_prompt(rz_cons_singleton()->line, prompt); *buf = 0; rz_cons_fgets(buf, len, 0, NULL); } diff --git a/librz/core/tui/rop.c b/librz/core/tui/rop.c index 0781fffe365..1602f429a4b 100644 --- a/librz/core/tui/rop.c +++ b/librz/core/tui/rop.c @@ -21,25 +21,26 @@ RZ_IPI int rz_core_visual_view_rop(RzCore *core) { RzListIter *iter; const int rows = 7; int cur = 0; + RzLine *line = core->cons->line; - rz_line_set_prompt("rop regexp: "); - const char *line = rz_line_readline(); + rz_line_set_prompt(line, "rop regexp: "); + const char *linestr = rz_line_readline(line); + if (RZ_STR_ISEMPTY(linestr)) { + return false; + } int scr_h, scr_w = rz_cons_get_size(&scr_h); - if (!line || !*line) { - return false; - } // maybe store in RzCore, so we can save it in project and use it outside visual eprintf("Searching ROP gadgets...\n"); - char *ropstr = rz_core_cmd_strf(core, "\"/Rl %s\" @e:scr.color=0", line); + char *ropstr = rz_core_cmd_strf(core, "\"/Rl %s\" @e:scr.color=0", linestr); RzList *rops = rz_str_split_list(ropstr, "\n", 0); int delta = 0; bool show_color = core->print->flags & RZ_PRINT_FLAGS_COLOR; bool forceaddr = false; ut64 addr = UT64_MAX; - char *cursearch = strdup(line); + char *cursearch = strdup(linestr); while (true) { rz_cons_clear00(); rz_cons_printf("[0x%08" PFMT64x "]-[visual-rzrop] %s (see pdp command)\n", @@ -139,7 +140,7 @@ RZ_IPI int rz_core_visual_view_rop(RzCore *core) { while (true) { char cmd[1024]; cmd[0] = '\0'; - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } @@ -159,10 +160,10 @@ RZ_IPI int rz_core_visual_view_rop(RzCore *core) { rz_core_yank_hexpair(core, chainstr); break; case 'o': { - rz_line_set_prompt("offset: "); - const char *line = rz_line_readline(); - if (line && *line) { - ut64 off = rz_num_math(core->num, line); + rz_line_set_prompt(line, "offset: "); + const char *linestr = rz_line_readline(line); + if (RZ_STR_ISNOTEMPTY(linestr)) { + ut64 off = rz_num_math(core->num, linestr); rz_core_seek(core, off, true); addr = off; forceaddr = true; @@ -170,16 +171,16 @@ RZ_IPI int rz_core_visual_view_rop(RzCore *core) { } } break; case 'r': { - rz_line_set_prompt("rop regexp: "); - const char *line = rz_line_readline(); - if (line && *line) { + rz_line_set_prompt(line, "rop regexp: "); + const char *linestr = rz_line_readline(line); + if (RZ_STR_ISNOTEMPTY(linestr)) { free(cursearch); delta = 0; addr = UT64_MAX; cur = 0; - cursearch = strdup(line); + cursearch = strdup(linestr); free(ropstr); - ropstr = rz_core_cmd_strf(core, "\"/Rl %s\" @e:scr.color=0", line); + ropstr = rz_core_cmd_strf(core, "\"/Rl %s\" @e:scr.color=0", linestr); rz_list_free(rops); rops = rz_str_split_list(ropstr, "\n", 0); } @@ -188,18 +189,18 @@ RZ_IPI int rz_core_visual_view_rop(RzCore *core) { rz_core_prompt_highlight(core); break; case 'i': { - rz_line_set_prompt("insert value: "); - const char *line = rz_line_readline(); - if (line && *line) { - ut64 n = rz_num_math(core->num, line); + rz_line_set_prompt(line, "insert value: "); + const char *linestr = rz_line_readline(line); + if (RZ_STR_ISNOTEMPTY(linestr)) { + ut64 n = rz_num_math(core->num, linestr); rz_list_push(core->ropchain, rz_str_newf("0x%08" PFMT64x, n)); } } break; case ';': { - rz_line_set_prompt("comment: "); - const char *line = rz_line_readline(); - if (line && *line) { - rz_meta_set_string(core->analysis, RZ_META_TYPE_COMMENT, addr + delta, line); + rz_line_set_prompt(line, "comment: "); + const char *linestr = rz_line_readline(line); + if (RZ_STR_ISNOTEMPTY(linestr)) { + rz_meta_set_string(core->analysis, RZ_META_TYPE_COMMENT, addr + delta, linestr); } } break; case '.': diff --git a/librz/core/tui/tabs.c b/librz/core/tui/tabs.c index a72dedfb203..8ed9a4c4357 100644 --- a/librz/core/tui/tabs.c +++ b/librz/core/tui/tabs.c @@ -12,7 +12,7 @@ static void prompt_read(const char *p, char *buf, int buflen) { return; } *buf = 0; - rz_line_set_prompt(p); + rz_line_set_prompt(rz_cons_singleton()->line, p); rz_core_visual_showcursor(NULL, true); rz_cons_fgets(buf, buflen, 0, NULL); rz_core_visual_showcursor(NULL, false); diff --git a/librz/core/tui/vasm.c b/librz/core/tui/vasm.c index 2326b8313b8..004b7f0cf41 100644 --- a/librz/core/tui/vasm.c +++ b/librz/core/tui/vasm.c @@ -78,7 +78,7 @@ RZ_IPI void rz_core_visual_asm(RzCore *core, ut64 off) { rz_io_read_at(core->io, off, cva.buf, sizeof(cva.buf)); cva.blocklen = rz_hex_bin2str(cva.buf, sizeof(cva.buf), cva.blockbuf); - rz_line_readline_cb(readline_callback, &cva); + rz_line_readline_cb(core->cons->line, readline_callback, &cva); if (cva.acode && cva.acode->len > 0) { if (rz_cons_yesno('y', "Save changes? (Y/n)")) { diff --git a/librz/core/tui/visual.c b/librz/core/tui/visual.c index 5e483ff99b8..9984959f3bd 100644 --- a/librz/core/tui/visual.c +++ b/librz/core/tui/visual.c @@ -565,7 +565,7 @@ static void prompt_read(const char *p, char *buf, int buflen) { return; } *buf = 0; - rz_line_set_prompt(p); + rz_line_set_prompt(rz_cons_singleton()->line, p); rz_core_visual_showcursor(NULL, true); rz_cons_fgets(buf, buflen, 0, NULL); rz_core_visual_showcursor(NULL, false); @@ -657,20 +657,21 @@ RZ_IPI void rz_core_visual_prompt_input(RzCore *core) { RZ_IPI int rz_core_visual_prompt(RzCore *core) { char buf[1024]; int ret; + RzLine *line = core->cons->line; if (PIDX != 2) { core->seltab = 0; } #if __UNIX__ - rz_line_set_prompt(Color_RESET ":> "); + rz_line_set_prompt(line, Color_RESET ":> "); #else - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); #endif rz_core_visual_showcursor(core, true); rz_cons_fgets(buf, sizeof(buf), 0, NULL); if (!strcmp(buf, "q")) { ret = false; } else if (*buf) { - rz_line_hist_add(buf); + rz_line_hist_add(line, buf); rz_core_cmd(core, buf, 0); rz_cons_echo(NULL); rz_cons_flush(); @@ -905,7 +906,7 @@ static void visual_search(RzCore *core) { int len, d = core->print->cur; char str[128], buf[sizeof(str) * 2 + 1]; - rz_line_set_prompt("search byte/string in block: "); + rz_line_set_prompt(core->cons->line, "search byte/string in block: "); rz_cons_fgets(str, sizeof(str), 0, NULL); len = rz_hex_str2bin(str, (ut8 *)buf); if (*str == '"') { @@ -1055,12 +1056,13 @@ RZ_IPI int rz_line_hist_offset_down(RzLine *line) { RZ_IPI void rz_core_visual_offset(RzCore *core) { char buf[256]; + RzLine *line = core->cons->line; - core->cons->line->prompt_type = RZ_LINE_PROMPT_OFFSET; - rz_line_set_hist_callback(core->cons->line, + line->prompt_type = RZ_LINE_PROMPT_OFFSET; + rz_line_set_hist_callback(line, &rz_line_hist_offset_up, &rz_line_hist_offset_down); - rz_line_set_prompt("[offset]> "); + rz_line_set_prompt(line, "[offset]> "); if (rz_cons_fgets(buf, sizeof(buf) - 1, 0, NULL) > 0) { if (!strcmp(buf, "g") || !strcmp(buf, "G")) { __core_visual_gogo(core, buf[0]); @@ -1074,8 +1076,8 @@ RZ_IPI void rz_core_visual_offset(RzCore *core) { } reset_print_cur(core->print); } - rz_line_set_hist_callback(core->cons->line, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); - core->cons->line->prompt_type = RZ_LINE_PROMPT_DEFAULT; + rz_line_set_hist_callback(line, &rz_line_hist_cmd_up, &rz_line_hist_cmd_down); + line->prompt_type = RZ_LINE_PROMPT_DEFAULT; } RZ_IPI int rz_core_visual_prevopsz(RzCore *core, ut64 addr) { @@ -1089,7 +1091,7 @@ static void add_comment(RzCore *core, ut64 addr, const char *prompt) { rz_core_visual_showcursor(core, true); rz_cons_flush(); rz_cons_set_raw(false); - rz_line_set_prompt(":> "); + rz_line_set_prompt(core->cons->line, ":> "); rz_cons_enable_mouse(false); if (rz_cons_fgets(buf, sizeof(buf), 0, NULL) < 0) { buf[0] = '\0'; @@ -2048,6 +2050,7 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { RzAsmOp op; ut64 offset = core->offset; RzCoreVisual *visual = core->visual; + RzLine *line = core->cons->line; char buf[4096]; const char *key_s; int i, cols = core->print->cols; @@ -2202,7 +2205,7 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { rz_cons_flush(); rz_cons_set_raw(false); strcpy(buf, "\"wa "); - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); rz_cons_enable_mouse(false); if (rz_cons_fgets(buf + 4, sizeof(buf) - 4, 0, NULL) < 0) { buf[0] = '\0'; @@ -2231,9 +2234,9 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { const char *buf = NULL; #define I core->cons const char *cmd = rz_config_get(core->config, "cmd.vprompt"); - rz_line_set_prompt("cmd.vprompt> "); + rz_line_set_prompt(line, "cmd.vprompt> "); I->line->contents = strdup(cmd); - buf = rz_line_readline(); + buf = rz_line_readline(line); I->line->contents = NULL; (void)rz_config_set(core->config, "cmd.vprompt", buf); rz_core_visual_showcursor(core, false); @@ -2243,16 +2246,16 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { const char *buf = NULL; #define I core->cons const char *cmd = rz_config_get(core->config, "cmd.cprompt"); - rz_line_set_prompt("cmd.cprompt> "); - I->line->contents = strdup(cmd); - buf = rz_line_readline(); + rz_line_set_prompt(line, "cmd.cprompt> "); + line->contents = strdup(cmd); + buf = rz_line_readline(line); if (buf && !strcmp(buf, "|")) { - RZ_FREE(I->line->contents); + RZ_FREE(line->contents); core->print->cur_enabled = true; core->print->cur = 0; (void)rz_config_set(core->config, "cmd.cprompt", "p=e $r-2"); } else { - RZ_FREE(I->line->contents); + RZ_FREE(line->contents); (void)rz_config_set(core->config, "cmd.cprompt", buf ? buf : ""); } rz_core_visual_showcursor(core, false); @@ -2328,7 +2331,7 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { bool mouse_state = __holdMouseState(core); int range, min, max; char name[256], *n; - rz_line_set_prompt("flag name: "); + rz_line_set_prompt(line, "flag name: "); rz_core_visual_showcursor(core, true); if (rz_cons_fgets(name, sizeof(name), 0, NULL) >= 0 && *name) { n = name; @@ -2459,7 +2462,7 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { rz_cons_set_raw(0); if (ch == 'I') { strcpy(buf, "wb "); - rz_line_set_prompt("insert hexpair block: "); + rz_line_set_prompt(line, "insert hexpair block: "); if (rz_cons_fgets(buf + 4, sizeof(buf) - 4, 0, NULL) < 0) { buf[0] = '\0'; } @@ -2476,13 +2479,13 @@ RZ_IPI int rz_core_visual_cmd(RzCore *core, const char *arg) { } if (core->print->col == 2) { strcpy(buf, "\"w "); - rz_line_set_prompt("insert string: "); + rz_line_set_prompt(line, "insert string: "); if (rz_cons_fgets(buf + 3, sizeof(buf) - 3, 0, NULL) < 0) { buf[0] = '\0'; } strcat(buf, "\""); } else { - rz_line_set_prompt("insert hex: "); + rz_line_set_prompt(line, "insert hex: "); if (core->print->ocur != -1) { int bs = RZ_ABS(core->print->cur - core->print->ocur) + 1; core->blocksize = bs; diff --git a/librz/core/tui/vmenus.c b/librz/core/tui/vmenus.c index c24480b14bf..ba43f125de7 100644 --- a/librz/core/tui/vmenus.c +++ b/librz/core/tui/vmenus.c @@ -556,7 +556,7 @@ static char *__prompt(const char *msg, void *p) { char res[128]; rz_cons_show_cursor(true); rz_cons_set_raw(false); - rz_line_set_prompt(msg); + rz_line_set_prompt(rz_cons_singleton()->line, msg); res[0] = 0; if (!rz_cons_fgets(res, sizeof(res), 0, NULL)) { res[0] = 0; @@ -594,6 +594,7 @@ RZ_IPI void rz_core_visual_analysis(RzCore *core, const char *input) { char old[218]; int nfcns, ch = 0; + RzLine *line = core->cons->line; RzCoreVisual *visual = core->visual; RzConsEvent olde = core->cons->event_resize; void *olde_user = core->cons->event_data; @@ -746,7 +747,7 @@ RZ_IPI void rz_core_visual_analysis(RzCore *core, const char *input) { case 1: rz_cons_show_cursor(true); rz_cons_set_raw(false); - rz_line_set_prompt("New name: "); + rz_line_set_prompt(line, "New name: "); if (rz_cons_fgets(old, sizeof(old), 0, NULL)) { if (*old) { // old[strlen (old)-1] = 0; @@ -755,7 +756,7 @@ RZ_IPI void rz_core_visual_analysis(RzCore *core, const char *input) { } break; default: - rz_line_set_prompt("New name: "); + rz_line_set_prompt(line, "New name: "); if (rz_cons_fgets(old, sizeof(old), 0, NULL)) { if (*old) { // old[strlen (old)-1] = 0; @@ -771,7 +772,7 @@ RZ_IPI void rz_core_visual_analysis(RzCore *core, const char *input) { if (level == 1) { rz_cons_show_cursor(true); rz_cons_set_raw(false); - rz_line_set_prompt("New type: "); + rz_line_set_prompt(line, "New type: "); if (rz_cons_fgets(old, sizeof(old), 0, NULL)) { if (*old) { // old[strlen (old)-1] = 0; diff --git a/librz/core/tui/vmenus_graph.c b/librz/core/tui/vmenus_graph.c index 85bafda8cea..a62e58222bc 100644 --- a/librz/core/tui/vmenus_graph.c +++ b/librz/core/tui/vmenus_graph.c @@ -257,6 +257,7 @@ RZ_IPI int __core_visual_view_graph_update(RzCore *core, RzCoreVisualViewGraph * RZ_IPI int rz_core_visual_view_graph(RzCore *core) { RzCoreVisualViewGraph status = { 0 }; + RzLine *line = core->cons->line; status.core = core; status.cur_sort = SORT_NAME; __reset_status(&status); @@ -381,7 +382,7 @@ RZ_IPI int rz_core_visual_view_graph(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); cmd[0] = '\0'; - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } @@ -398,7 +399,7 @@ RZ_IPI int rz_core_visual_view_graph(RzCore *core) { rz_cons_show_cursor(true); rz_cons_set_raw(0); cmd[0] = '\0'; - rz_line_set_prompt(":> "); + rz_line_set_prompt(line, ":> "); if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) { cmd[0] = '\0'; } diff --git a/librz/include/rz_cons.h b/librz/include/rz_cons.h index 613804b3680..26f0445aabf 100644 --- a/librz/include/rz_cons.h +++ b/librz/include/rz_cons.h @@ -1203,29 +1203,28 @@ struct rz_line_t { #ifdef RZ_API -RZ_API RzLine *rz_line_new(void); -RZ_API RzLine *rz_line_singleton(void); -RZ_API void rz_line_free(void); -RZ_API RZ_OWN char *rz_line_get_prompt(void); -RZ_API void rz_line_set_prompt(const char *prompt); -RZ_API bool rz_line_dietline_init(void); -RZ_API void rz_line_clipboard_push(const char *str); -RZ_API void rz_line_hist_free(void); -RZ_API void rz_line_autocomplete(void); +RZ_API RZ_OWN RzLine *rz_line_new(void); +RZ_API void rz_line_free(RZ_NULLABLE RzLine *line); +RZ_API RZ_OWN char *rz_line_get_prompt(RZ_NONNULL RzLine *line); +RZ_API void rz_line_set_prompt(RZ_NONNULL RzLine *line, RZ_NONNULL const char *prompt); +RZ_API bool rz_line_dietline_init(RZ_NONNULL RzLine *line); +RZ_API void rz_line_clipboard_push(RZ_NONNULL RzLine *line, RZ_NONNULL const char *str); +RZ_API void rz_line_hist_free(RZ_NULLABLE RzLine *line); +RZ_API void rz_line_autocomplete(RZ_NONNULL RzLine *line); typedef int(RzLineReadCallback)(void *user, const char *line); -RZ_API const char *rz_line_readline(void); -RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user); - -RZ_API int rz_line_hist_load(RZ_NONNULL const char *file); -RZ_API int rz_line_hist_add(const char *line); -RZ_API int rz_line_hist_save(RZ_NONNULL const char *file); -RZ_API int rz_line_hist_list(void); -RZ_API const char *rz_line_hist_get(int n); - -RZ_API int rz_line_set_hist_callback(RzLine *line, RzLineHistoryUpCb cb_up, RzLineHistoryDownCb cb_down); -RZ_API int rz_line_hist_cmd_up(RzLine *line); -RZ_API int rz_line_hist_cmd_down(RzLine *line); +RZ_API const char *rz_line_readline(RZ_NONNULL RzLine *line); +RZ_API const char *rz_line_readline_cb(RZ_NONNULL RzLine *line, RzLineReadCallback cb, void *user); + +RZ_API bool rz_line_hist_load(RZ_NONNULL RzLine *line, RZ_NONNULL const char *file); +RZ_API bool rz_line_hist_add(RZ_NONNULL RzLine *line, RZ_NONNULL const char *str); +RZ_API bool rz_line_hist_save(RZ_NONNULL RzLine *line, const char *file); +RZ_API int rz_line_hist_list(RZ_NONNULL RzLine *line); +RZ_API const char *rz_line_hist_get(RZ_NONNULL RzLine *line, int n); + +RZ_API int rz_line_set_hist_callback(RZ_NONNULL RzLine *line, RzLineHistoryUpCb cb_up, RzLineHistoryDownCb cb_down); +RZ_API int rz_line_hist_cmd_up(RZ_NONNULL RzLine *line); +RZ_API int rz_line_hist_cmd_down(RZ_NONNULL RzLine *line); RZ_API void rz_line_completion_init(RzLineCompletion *completion, size_t args_limit); RZ_API void rz_line_completion_fini(RzLineCompletion *completion); diff --git a/librz/io/p/io_windbg.c b/librz/io/p/io_windbg.c index 4a81109a036..83a06993563 100644 --- a/librz/io/p/io_windbg.c +++ b/librz/io/p/io_windbg.c @@ -151,11 +151,12 @@ static STDMETHODIMP __system_error_cb(PDEBUG_EVENT_CALLBACKS This, ULONG Error, static STDMETHODIMP __input_cb(PDEBUG_INPUT_CALLBACKS This, ULONG BufferSize) { char prompt[512]; + RzLine *line = rz_cons_singleton()->line; PDEBUG_INPUT_CALLBACKS_IMPL impl = (PDEBUG_INPUT_CALLBACKS_IMPL)This; DbgEngContext *idbg = impl->m_idbg; ITHISCALL(dbgCtrl, GetPromptText, prompt, sizeof(prompt), NULL); - rz_line_set_prompt(prompt); - const char *str = rz_line_readline(); + rz_line_set_prompt(line, prompt); + const char *str = rz_line_readline(line); char *ret = rz_str_ndup(str, RZ_MIN(strlen(str), BufferSize)); ITHISCALL(dbgCtrl, ReturnInput, ret); return S_OK; diff --git a/librz/lang/lang.c b/librz/lang/lang.c index a9baf30b276..ef4b509f84f 100644 --- a/librz/lang/lang.c +++ b/librz/lang/lang.c @@ -229,7 +229,7 @@ RZ_API int rz_lang_prompt(RzLang *lang) { return true; } /* init line */ - RzLine *line = rz_line_singleton(); + RzLine *line = rz_cons_singleton()->line; RzLineHistory hist = line->history; RzLineHistory histnull = { 0 }; RzLineCompletion oc = line->completion; @@ -242,12 +242,12 @@ RZ_API int rz_lang_prompt(RzLang *lang) { for (;;) { rz_cons_flush(); snprintf(buf, sizeof(buf) - 1, "%s> ", lang->cur->name); - rz_line_set_prompt(buf); - p = rz_line_readline(); + rz_line_set_prompt(line, buf); + p = rz_line_readline(line); if (!p) { break; } - rz_line_hist_add(p); + rz_line_hist_add(line, p); strncpy(buf, p, sizeof(buf) - 1); if (*buf == '!') { if (buf[1]) { @@ -289,7 +289,7 @@ RZ_API int rz_lang_prompt(RzLang *lang) { } } // XXX: leaking history - rz_line_set_prompt(prompt); + rz_line_set_prompt(line, prompt); line->completion = oc; line->history = hist; clearerr(stdin); diff --git a/librz/main/rizin.c b/librz/main/rizin.c index 3b0272b9b6d..bb74ea855ec 100644 --- a/librz/main/rizin.c +++ b/librz/main/rizin.c @@ -1500,7 +1500,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) { if (mustSaveHistory(r->config)) { char *history = rz_path_home_history(); - rz_line_hist_save(history); + rz_line_hist_save(r->cons->line, history); free(history); } diff --git a/librz/main/rz-diff.c b/librz/main/rz-diff.c index fbc53fae84e..2299fab7a6a 100644 --- a/librz/main/rz-diff.c +++ b/librz/main/rz-diff.c @@ -2646,7 +2646,7 @@ static char *visual_prompt(DiffHexView *hview, const char *prompt) { rz_cons_gotoxy(0, hview->screen.height); rz_cons_clear_line(0); rz_cons_printf("%s%s ", hview->colors.reset, prompt); - rz_line_set_prompt(":> "); + rz_line_set_prompt(rz_cons_singleton()->line, ":> "); rz_cons_flush(); rz_cons_fgets(buf, sizeof(buf), 0, NULL); if (*buf) { diff --git a/test/unit/test_cons.c b/test/unit/test_cons.c index 2b0b0aa7746..84a711efe46 100644 --- a/test/unit/test_cons.c +++ b/test/unit/test_cons.c @@ -196,13 +196,13 @@ bool test_line_nocompletion(void) { strcpy(line->buffer.data, "pd"); line->buffer.length = strlen("pd"); line->buffer.index = 2; - rz_line_autocomplete(); + rz_line_autocomplete(line); mu_assert_streq(line->buffer.data, "pd", "pd is still there"); mu_assert_eq(line->buffer.length, 2, "length is still 2"); mu_assert_eq(line->buffer.index, 2, "the user position is still the same"); - rz_line_free(); + rz_line_free(line); mu_end; } @@ -219,7 +219,7 @@ bool test_line_onecompletion(void) { strcpy(line->buffer.data, "pd"); line->buffer.length = strlen("pd"); line->buffer.index = 2; - rz_line_autocomplete(); + rz_line_autocomplete(line); mu_assert_eq(line->buffer.length, 4, "length is updated (space included)"); mu_assert_eq(line->buffer.index, 4, "index after the space"); @@ -228,13 +228,13 @@ bool test_line_onecompletion(void) { strcpy(line->buffer.data, "pd fcn"); line->buffer.length = strlen("pd fcn"); line->buffer.index = 2; - rz_line_autocomplete(); + rz_line_autocomplete(line); mu_assert_eq(line->buffer.index, 3, "should leave everythin else intact"); mu_assert_eq(line->buffer.length, 7, "length is updated"); mu_assert_streq(line->buffer.data, "pdf fcn", "pdf has been autocompleted and fcn kept intact"); - rz_line_free(); + rz_line_free(line); mu_end; } @@ -261,7 +261,6 @@ bool test_line_multicompletion(void) { // Make test reproducible everywhere cons->force_columns = 80; cons->force_rows = 23; - rz_line_free(); RzLine *line = rz_line_new(); line->ns_completion.run = multicompletion_run; cons->line = line; @@ -269,7 +268,7 @@ bool test_line_multicompletion(void) { strcpy(line->buffer.data, "pd"); line->buffer.length = strlen("pd"); line->buffer.index = 2; - rz_line_autocomplete(); + rz_line_autocomplete(line); mu_assert_eq(line->buffer.length, 2, "length is the same"); mu_assert_eq(line->buffer.index, 2, "index is the same"); @@ -286,7 +285,7 @@ bool test_line_multicompletion(void) { strcpy(line->buffer.data, "p"); line->buffer.length = strlen("p"); line->buffer.index = 1; - rz_line_autocomplete(); + rz_line_autocomplete(line); mu_assert_eq(line->buffer.length, 2, "length was updated for 'pd'"); mu_assert_eq(line->buffer.index, 2, "index is at the end of 'pd'"); @@ -307,7 +306,6 @@ bool test_line_kill_word(void) { // Make test reproducible everywhere cons->force_columns = 80; cons->force_rows = 23; - rz_line_free(); RzLine *line = rz_line_new(); line->ns_completion.run = multicompletion_run; cons->line = line; @@ -315,7 +313,7 @@ bool test_line_kill_word(void) { // write the string, then do ^b two times to move the index to 10, then ^d to delete the word under the cursor const char instr[] = "pd 10@ hello\x1b\x62\x1b\x62\x1b\x64\n"; rz_cons_readpush(instr, sizeof(instr)); - rz_line_readline(); + rz_line_readline(line); mu_assert_eq(line->buffer.index, 3, "index is after 'pd '"); mu_assert_streq(line->buffer.data, "pd @ hello", "10 was deleted"); @@ -329,28 +327,27 @@ bool test_line_undo(void) { // Make test reproducible everywhere cons->force_columns = 80; cons->force_rows = 23; - rz_line_free(); RzLine *line = rz_line_new(); cons->line = line; // write 20 chars and undo once char input_concat[] = "01234567890123456789\x1f\n"; rz_cons_readpush(input_concat, sizeof(input_concat)); - rz_line_readline(); + rz_line_readline(line); mu_assert_eq(line->buffer.length, 0, "concatenated string should get cleared"); mu_assert_eq(line->buffer.index, 0, "index is 0"); // write a string, delete, then undo('\x1f') twice char input_undo[] = "0123\x17\x1f\x1f\n"; rz_cons_readpush(input_undo, sizeof(input_undo)); - rz_line_readline(); + rz_line_readline(line); mu_assert_eq(line->buffer.index, 0, "index is at 0"); mu_assert_eq(line->buffer.length, 0, "legth is 0"); // write a string, undo('\x1f') and redo('\x1b\x3f') char input_redo[] = "pDF\x1f\x1b\x3f\n"; rz_cons_readpush(input_redo, sizeof(input_redo)); - rz_line_readline(); + rz_line_readline(line); mu_assert_streq(line->buffer.data, "pDF", "redo not working"); // run completion (example of replacing and continuous operation). @@ -358,7 +355,7 @@ bool test_line_undo(void) { // now "pd" has been confirmed to be completed to "pdf ". undo will turn it to previous state replacing the texts. const char input_undo_group[] = "pd\t\x1f\n"; rz_cons_readpush(input_undo_group, sizeof(input_undo_group)); - rz_line_readline(); + rz_line_readline(line); mu_assert_streq(line->buffer.data, "pd", "undo group operations not working"); rz_cons_free();