diff options
-rw-r--r-- | buffer.c | 4 | ||||
-rw-r--r-- | menu.c | 40 | ||||
-rw-r--r-- | session.c | 37 | ||||
-rw-r--r-- | ted.c | 1 | ||||
-rw-r--r-- | ted.h | 1 |
5 files changed, 72 insertions, 11 deletions
@@ -1249,6 +1249,8 @@ static Status buffer_insert_lines(TextBuffer *buffer, u32 where, u32 number) { // inserts the given text, returning the position of the end of the text BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 str) { + buffer_pos_validate(buffer, &pos); + if (buffer->view_only) return pos; if (str.len > U32_MAX) { @@ -1480,6 +1482,8 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_) if (nchars_ > U32_MAX) nchars_ = U32_MAX; u32 nchars = (u32)nchars_; + buffer_pos_validate(buffer, &pos); + // Correct nchars in case it goes past the end of the file. // Why do we need to correct it? // When generating undo events, we allocate nchars characters of memory (see buffer_edit below). @@ -29,6 +29,7 @@ static void menu_close(Ted *ted) { case MENU_COMMAND_SELECTOR: buffer_clear(&ted->line_buffer); buffer_clear(&ted->argument_buffer); + free(ted->command_selector.entries); break; } ted->menu = MENU_NONE; @@ -70,10 +71,10 @@ static void menu_open(Ted *ted, Menu menu) { case MENU_GOTO_LINE: ted_switch_to_buffer(ted, &ted->line_buffer); break; - case MENU_COMMAND_SELECTOR: + case MENU_COMMAND_SELECTOR: { ted_switch_to_buffer(ted, &ted->line_buffer); buffer_insert_char_at_cursor(&ted->argument_buffer, '1'); - break; + } break; } } @@ -244,6 +245,36 @@ static void menu_update(Ted *ted) { line_buffer->line_buffer_submitted = false; free(contents); } break; + case MENU_COMMAND_SELECTOR: { + Selector *selector = &ted->command_selector; + SelectorEntry *entries = selector->entries = calloc(arr_count(command_names), sizeof *selector->entries); + if (entries) { + for (size_t i = 0; i < arr_count(command_names); ++i) { + if (command_names[i].cmd != CMD_UNKNOWN) { + char const *name = command_names[i].name; + entries[i].name = name; + entries[i].color = COLOR_TEXT; + } + } + selector->n_entries = arr_count(command_names); + } + + char *chosen_command = selector_update(ted, &ted->command_selector); + if (chosen_command) { + Command c = command_from_str(chosen_command); + char *argument = str32_to_utf8_cstr(buffer_get_line(&ted->argument_buffer, 0)), *endp = NULL; + long long arg = strtoll(argument, &endp, 0); + + if (*endp == '\0') { + menu_close(ted); + command_execute(ted, c, arg); + } + + free(argument); + free(chosen_command); + } + free(selector->entries); selector->entries = NULL; selector->n_entries = 0; + } break; } } @@ -277,7 +308,7 @@ static void menu_render(Ted *ted) { float menu_x1, menu_y1, menu_x2, menu_y2; rect_coords(bounds, &menu_x1, &menu_y1, &menu_x2, &menu_y2); - if (menu == MENU_OPEN || menu == MENU_SAVE_AS || menu == MENU_GOTO_DEFINITION) { + if (menu == MENU_OPEN || menu == MENU_SAVE_AS || menu == MENU_GOTO_DEFINITION || menu == MENU_COMMAND_SELECTOR) { // menu rectangle & border gl_geometry_rect(bounds, colors[COLOR_MENU_BG]); gl_geometry_rect_border(bounds, settings->border_thickness, colors[COLOR_BORDER]); @@ -345,5 +376,8 @@ static void menu_render(Ted *ted) { // line buffer buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y2)); } break; + case MENU_COMMAND_SELECTOR: + selector_render(ted, &ted->command_selector); + break; } } @@ -93,8 +93,8 @@ static void session_read_buffer(Ted *ted, FILE *fp) { static void session_write_file(Ted *ted, FILE *fp) { fwrite(SESSION_VERSION, 1, sizeof SESSION_VERSION, fp); - write_u16(fp, (u16)(ted->active_node - ted->nodes)); // active node idx - write_u16(fp, (u16)(ted->active_buffer - ted->buffers)); // active buffer idx + write_u16(fp, ted->active_node ? (u16)(ted->active_node - ted->nodes) : U16_MAX); // active node idx + write_u16(fp, ted->active_buffer ? (u16)(ted->active_buffer - ted->buffers) : U16_MAX); // active buffer idx u16 nnodes = 0; for (u16 i = 0; i < TED_MAX_NODES; ++i) @@ -121,8 +121,8 @@ static void session_read_file(Ted *ted, FILE *fp) { return; // wrong version } - u16 active_node_idx = clamp_u16(read_u16(fp), 0, TED_MAX_NODES); - u16 active_buffer_idx = clamp_u16(read_u16(fp), 0, TED_MAX_BUFFERS); + u16 active_node_idx = read_u16(fp); + u16 active_buffer_idx = read_u16(fp); u16 nnodes = clamp_u16(read_u16(fp), 0, TED_MAX_NODES); for (u16 i = 0; i < nnodes; ++i) { @@ -134,10 +134,31 @@ static void session_read_file(Ted *ted, FILE *fp) { session_read_buffer(ted, fp); } - if (ted->nodes_used[active_node_idx]) - ted->active_node = &ted->nodes[active_node_idx]; - if (ted->buffers_used[active_buffer_idx]) - ted->active_buffer = &ted->buffers[active_buffer_idx]; + if (active_node_idx == U16_MAX) { + ted->active_node = NULL; + } else { + active_node_idx = clamp_u16(active_node_idx, 0, TED_MAX_NODES); + if (ted->nodes_used[active_node_idx]) + ted->active_node = &ted->nodes[active_node_idx]; + } + + if (active_buffer_idx == U16_MAX) { + ted->active_buffer = NULL; + } else { + active_buffer_idx = clamp_u16(active_buffer_idx, 0, TED_MAX_BUFFERS); + if (ted->buffers_used[active_buffer_idx]) + ted->active_buffer = &ted->buffers[active_buffer_idx]; + } + + if (nbuffers && !ted->active_buffer) { + // set active buffer to something + for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) { + if (ted->buffers_used[i]) { + ted_switch_to_buffer(ted, &ted->buffers[i]); + break; + } + } + } } static void session_write(Ted *ted) { @@ -1,5 +1,6 @@ static void menu_open(Ted *ted, Menu menu); static void find_update(Ted *ted, bool force); +static Command command_from_str(char const *str); // this is a macro so we get -Wformat warnings #define ted_seterr(ted, ...) \ @@ -254,6 +254,7 @@ typedef struct Ted { Menu menu; FileSelector file_selector; Selector tag_selector; // for "go to definition of..." menu + Selector command_selector; TextBuffer line_buffer; // general-purpose line buffer for inputs -- used for menus TextBuffer find_buffer; // use for "find" term in find/find+replace TextBuffer replace_buffer; // "replace" for find+replace |