diff options
-rw-r--r-- | buffer.c | 12 | ||||
-rw-r--r-- | colors.h | 4 | ||||
-rw-r--r-- | command.c | 67 | ||||
-rw-r--r-- | command.h | 2 | ||||
-rw-r--r-- | main.c | 138 | ||||
-rw-r--r-- | ted-base.c | 12 | ||||
-rw-r--r-- | ted.cfg | 4 | ||||
-rw-r--r-- | ted.h | 9 |
8 files changed, 161 insertions, 87 deletions
@@ -1258,6 +1258,14 @@ void buffer_select_all(TextBuffer *buffer) { buffer_select_to_pos(buffer, buffer_end_of_file(buffer)); } +// stop selecting +void buffer_disable_selection(TextBuffer *buffer) { + if (buffer->selection) { + buffer->cursor_pos = buffer->selection_pos; + buffer->selection = false; + } +} + static void buffer_shorten_line(Line *line, u32 new_len) { assert(line->len >= new_len); line->len = new_len; // @OPTIMIZE(memory): decrease line capacity @@ -1595,6 +1603,7 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { float char_width = text_font_char_width(font), char_height = text_font_char_height(font); float header_height = char_height; + Ted *ted = buffer->ted; Settings *settings = buffer_settings(buffer); u32 *colors = settings->colors; @@ -1758,7 +1767,8 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) { text_chars_end(font); - { // render cursor + if (buffer == ted->active_buffer) { + // render cursor float time_on = settings->cursor_blink_time_on; float time_off = settings->cursor_blink_time_off; bool is_on = true; @@ -7,6 +7,7 @@ ENUM_U16 { COLOR_BORDER, COLOR_TEXT, COLOR_SELECTION_BG, + COLOR_MENU_BG, COLOR_COUNT } ENUM_U16_END(ColorSetting); @@ -23,7 +24,8 @@ static ColorName const color_names[COLOR_COUNT] = { {COLOR_CURSOR_LINE_BG, "cursor-line-bg"}, {COLOR_BORDER, "border"}, {COLOR_TEXT, "text"}, - {COLOR_SELECTION_BG, "selection-bg"} + {COLOR_SELECTION_BG, "selection-bg"}, + {COLOR_MENU_BG, "menu-bg"} }; static ColorSetting color_setting_from_str(char const *str) { @@ -21,6 +21,7 @@ void command_execute(Ted *ted, Command c, i64 argument) { TextBuffer *buffer = ted->active_buffer; Settings *settings = &ted->settings; + switch (c) { case CMD_UNKNOWN: case CMD_COUNT: @@ -30,97 +31,100 @@ void command_execute(Ted *ted, Command c, i64 argument) { break; case CMD_LEFT: - buffer_cursor_move_left(buffer, argument); + if (buffer) buffer_cursor_move_left(buffer, argument); break; case CMD_RIGHT: - buffer_cursor_move_right(buffer, argument); + if (buffer) buffer_cursor_move_right(buffer, argument); break; case CMD_UP: - buffer_cursor_move_up(buffer, argument); + if (buffer) buffer_cursor_move_up(buffer, argument); break; case CMD_DOWN: - buffer_cursor_move_down(buffer, argument); + if (buffer) buffer_cursor_move_down(buffer, argument); break; case CMD_SELECT_LEFT: - buffer_select_left(buffer, argument); + if (buffer) buffer_select_left(buffer, argument); break; case CMD_SELECT_RIGHT: - buffer_select_right(buffer, argument); + if (buffer) buffer_select_right(buffer, argument); break; case CMD_SELECT_UP: - buffer_select_up(buffer, argument); + if (buffer) buffer_select_up(buffer, argument); break; case CMD_SELECT_DOWN: - buffer_select_down(buffer, argument); + if (buffer) buffer_select_down(buffer, argument); break; case CMD_LEFT_WORD: - buffer_cursor_move_left_words(buffer, argument); + if (buffer) buffer_cursor_move_left_words(buffer, argument); break; case CMD_RIGHT_WORD: - buffer_cursor_move_right_words(buffer, argument); + if (buffer) buffer_cursor_move_right_words(buffer, argument); break; case CMD_SELECT_LEFT_WORD: - buffer_select_left_words(buffer, argument); + if (buffer) buffer_select_left_words(buffer, argument); break; case CMD_SELECT_RIGHT_WORD: - buffer_select_right_words(buffer, argument); + if (buffer) buffer_select_right_words(buffer, argument); break; case CMD_START_OF_LINE: - buffer_cursor_move_to_start_of_line(buffer); + if (buffer) buffer_cursor_move_to_start_of_line(buffer); break; case CMD_END_OF_LINE: - buffer_cursor_move_to_end_of_line(buffer); + if (buffer) buffer_cursor_move_to_end_of_line(buffer); break; case CMD_SELECT_START_OF_LINE: - buffer_select_to_start_of_line(buffer); + if (buffer) buffer_select_to_start_of_line(buffer); break; case CMD_SELECT_END_OF_LINE: - buffer_select_to_end_of_line(buffer); + if (buffer) buffer_select_to_end_of_line(buffer); break; case CMD_START_OF_FILE: - buffer_cursor_move_to_start_of_file(buffer); + if (buffer) buffer_cursor_move_to_start_of_file(buffer); break; case CMD_END_OF_FILE: - buffer_cursor_move_to_end_of_file(buffer); + if (buffer) buffer_cursor_move_to_end_of_file(buffer); break; case CMD_SELECT_START_OF_FILE: - buffer_select_to_start_of_file(buffer); + if (buffer) buffer_select_to_start_of_file(buffer); break; case CMD_SELECT_END_OF_FILE: - buffer_select_to_end_of_file(buffer); + if (buffer) buffer_select_to_end_of_file(buffer); break; case CMD_SELECT_ALL: - buffer_select_all(buffer); + if (buffer) buffer_select_all(buffer); break; case CMD_BACKSPACE: - buffer_backspace_at_cursor(buffer, argument); + if (buffer) buffer_backspace_at_cursor(buffer, argument); break; case CMD_DELETE: - buffer_delete_chars_at_cursor(buffer, argument); + if (buffer) buffer_delete_chars_at_cursor(buffer, argument); break; case CMD_BACKSPACE_WORD: - buffer_backspace_words_at_cursor(buffer, argument); + if (buffer) buffer_backspace_words_at_cursor(buffer, argument); break; case CMD_DELETE_WORD: - buffer_delete_words_at_cursor(buffer, argument); + if (buffer) buffer_delete_words_at_cursor(buffer, argument); break; case CMD_PAGE_DOWN: - buffer_page_down(buffer, argument); + if (buffer) buffer_page_down(buffer, argument); break; case CMD_PAGE_UP: - buffer_page_up(buffer, argument); + if (buffer) buffer_page_up(buffer, argument); break; + case CMD_OPEN: + ted_menu_open(ted, MENU_OPEN); + break; case CMD_SAVE: - buffer_save(buffer); + if (buffer) buffer_save(buffer); break; case CMD_UNDO: - buffer_undo(buffer, argument); + if (buffer) buffer_undo(buffer, argument); break; case CMD_REDO: - buffer_redo(buffer, argument); + if (buffer) buffer_redo(buffer, argument); break; case CMD_TEXT_SIZE_INCREASE: { @@ -137,9 +141,10 @@ void command_execute(Ted *ted, Command c, i64 argument) { ted_load_font(ted); } } break; + } - if (buffer_haserr(buffer)) { + if (buffer && buffer_haserr(buffer)) { strncpy(ted->error, buffer_geterr(buffer), sizeof ted->error - 1); buffer_clearerr(buffer); } @@ -34,6 +34,7 @@ ENUM_U16 { CMD_BACKSPACE_WORD, CMD_DELETE_WORD, + CMD_OPEN, CMD_SAVE, CMD_UNDO, CMD_REDO, @@ -78,6 +79,7 @@ static CommandName const command_names[CMD_COUNT] = { {"delete", CMD_DELETE}, {"backspace-word", CMD_BACKSPACE_WORD}, {"delete-word", CMD_DELETE_WORD}, + {"open", CMD_OPEN}, {"save", CMD_SAVE}, {"undo", CMD_UNDO}, {"redo", CMD_REDO}, @@ -1,6 +1,5 @@ // @TODO: -// - text size (text-size, :increase-text-size, :decrease-text-size) -// - put stuff in UserData on windows +// - Windows installation #include "base.h" no_warn_start #if _WIN32 @@ -143,34 +142,39 @@ int main(int argc, char **argv) { if (ted_haserr(ted)) die("Error loadng font: %s", ted_geterr(ted)); + TextBuffer text_buffer; - TextBuffer *buffer = &text_buffer; - buffer_create(buffer, ted); - ted->active_buffer = buffer; + { + TextBuffer *buffer = &text_buffer; + buffer_create(buffer, ted); + ted->active_buffer = buffer; - char const *starting_filename = "Untitled"; - - switch (argc) { - case 0: case 1: break; - case 2: - starting_filename = argv[1]; - break; - default: - die("Usage: %s [filename]", argv[0]); - break; - } + char const *starting_filename = "Untitled"; + + switch (argc) { + case 0: case 1: break; + case 2: + starting_filename = argv[1]; + break; + default: + die("Usage: %s [filename]", argv[0]); + break; + } - if (fs_file_exists(starting_filename)) { - buffer_load_file(buffer, starting_filename); - if (buffer_haserr(buffer)) - die("Error loading file: %s", buffer_geterr(buffer)); - } else { - buffer_new_file(buffer, starting_filename); - if (buffer_haserr(buffer)) - die("Error creating file: %s", buffer_geterr(buffer)); + if (fs_file_exists(starting_filename)) { + buffer_load_file(buffer, starting_filename); + if (buffer_haserr(buffer)) + die("Error loading file: %s", buffer_geterr(buffer)); + } else { + buffer_new_file(buffer, starting_filename); + if (buffer_haserr(buffer)) + die("Error creating file: %s", buffer_geterr(buffer)); + } } + u32 *colors = settings->colors; + Uint32 time_at_last_frame = SDL_GetTicks(); bool quit = false; @@ -186,6 +190,7 @@ int main(int argc, char **argv) { Uint8 const *keyboard_state = SDL_GetKeyboardState(NULL); while (SDL_PollEvent(&event)) { + TextBuffer *buffer = ted->active_buffer; u32 key_modifier = (u32)ctrl_down << KEY_MODIFIER_CTRL_BIT | (u32)shift_down << KEY_MODIFIER_SHIFT_BIT | (u32)alt_down << KEY_MODIFIER_ALT_BIT; @@ -198,25 +203,28 @@ int main(int argc, char **argv) { // scroll with mouse wheel Sint32 dx = event.wheel.x, dy = -event.wheel.y; double scroll_speed = 2.5; - buffer_scroll(buffer, dx * scroll_speed, dy * scroll_speed); + if (ted->active_buffer) + buffer_scroll(ted->active_buffer, dx * scroll_speed, dy * scroll_speed); } break; case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { - BufferPos pos = {0}; - if (buffer_pixels_to_pos(buffer, V2((float)event.button.x, (float)event.button.y), &pos)) { - if (key_modifier == KEY_MODIFIER_SHIFT) { - buffer_select_to_pos(buffer, pos); - } else if (key_modifier == 0) { - buffer_cursor_move_to_pos(buffer, pos); - switch ((event.button.clicks - 1) % 3) { - case 0: break; // single-click - case 1: // double-click: select word - buffer_select_word(buffer); - break; - case 2: // triple-click: select line - buffer_select_line(buffer); - break; + if (buffer) { + BufferPos pos = {0}; + if (buffer_pixels_to_pos(buffer, V2((float)event.button.x, (float)event.button.y), &pos)) { + if (key_modifier == KEY_MODIFIER_SHIFT) { + buffer_select_to_pos(buffer, pos); + } else if (key_modifier == 0) { + buffer_cursor_move_to_pos(buffer, pos); + switch ((event.button.clicks - 1) % 3) { + case 0: break; // single-click + case 1: // double-click: select word + buffer_select_word(buffer); + break; + case 2: // triple-click: select line + buffer_select_line(buffer); + break; + } } } } @@ -225,9 +233,11 @@ int main(int argc, char **argv) { break; case SDL_MOUSEMOTION: if (event.motion.state == SDL_BUTTON_LMASK) { - BufferPos pos = {0}; - if (buffer_pixels_to_pos(buffer, V2((float)event.button.x, (float)event.button.y), &pos)) { - buffer_select_to_pos(buffer, pos); + if (buffer) { + BufferPos pos = {0}; + if (buffer_pixels_to_pos(buffer, V2((float)event.button.x, (float)event.button.y), &pos)) { + buffer_select_to_pos(buffer, pos); + } } } break; @@ -250,11 +260,19 @@ int main(int argc, char **argv) { (u32)((modifier & (KMOD_LCTRL|KMOD_RCTRL)) != 0) << KEY_MODIFIER_CTRL_BIT | (u32)((modifier & (KMOD_LSHIFT|KMOD_RSHIFT)) != 0) << KEY_MODIFIER_SHIFT_BIT | (u32)((modifier & (KMOD_LALT|KMOD_RALT)) != 0) << KEY_MODIFIER_ALT_BIT; + if (key_combo == SDL_SCANCODE_ESCAPE << 3) { + // escape key + if (ted->menu) { + ted_menu_close(ted, true); + } else if (buffer) { + buffer_disable_selection(buffer); + } + } if (key_combo < KEY_COMBO_COUNT) { KeyAction *action = &ted->key_actions[key_combo]; if (action->command) { command_execute(ted, action->command, action->argument); - } else switch (event.key.keysym.sym) { + } else if (buffer) switch (event.key.keysym.sym) { case SDLK_RETURN: buffer_insert_char_at_cursor(buffer, U'\n'); break; @@ -281,7 +299,8 @@ int main(int argc, char **argv) { } break; case SDL_TEXTINPUT: { char *text = event.text.text; - if (key_modifier == 0) // unfortunately, some key combinations like ctrl+minus still register as a "-" text input event + if (buffer + && key_modifier == 0) // unfortunately, some key combinations like ctrl+minus still register as a "-" text input event buffer_insert_utf8_at_cursor(buffer, text); } break; } @@ -302,19 +321,20 @@ int main(int argc, char **argv) { time_at_last_frame = time_this_frame; } - if (key_modifier == KEY_MODIFIER_ALT) { + TextBuffer *active_buffer = ted->active_buffer; + if (active_buffer && key_modifier == KEY_MODIFIER_ALT) { // alt + arrow keys to scroll double scroll_speed = 20.0; double scroll_amount_x = scroll_speed * frame_dt * 1.5; // characters are taller than they are wide double scroll_amount_y = scroll_speed * frame_dt; if (keyboard_state[SDL_SCANCODE_UP]) - buffer_scroll(buffer, 0, -scroll_amount_y); + buffer_scroll(active_buffer, 0, -scroll_amount_y); if (keyboard_state[SDL_SCANCODE_DOWN]) - buffer_scroll(buffer, 0, +scroll_amount_y); + buffer_scroll(active_buffer, 0, +scroll_amount_y); if (keyboard_state[SDL_SCANCODE_LEFT]) - buffer_scroll(buffer, -scroll_amount_x, 0); + buffer_scroll(active_buffer, -scroll_amount_x, 0); if (keyboard_state[SDL_SCANCODE_RIGHT]) - buffer_scroll(buffer, +scroll_amount_x, 0); + buffer_scroll(active_buffer, +scroll_amount_x, 0); } @@ -339,17 +359,27 @@ int main(int argc, char **argv) { { float x1 = 50, y1 = 50, x2 = window_widthf-50, y2 = window_heightf-50; - buffer_render(buffer, x1, y1, x2, y2); + buffer_render(&text_buffer, x1, y1, x2, y2); if (text_has_err()) { die("Text error: %s\n", text_get_err()); break; } } + if (ted->menu) { + glBegin(GL_QUADS); + gl_color_rgba(colors[COLOR_MENU_BG]); + rect_render(rect(V2(0, 0), V2(window_widthf, window_heightf))); + glEnd(); + switch (ted->menu) { + case MENU_NONE: assert(0); break; + case MENU_OPEN: + break; + } + } + #if DEBUG - //buffer_print_debug(buffer); - buffer_check_valid(buffer); - //buffer_print_undo_history(buffer); + buffer_check_valid(&text_buffer); #endif SDL_GL_SwapWindow(window); @@ -358,7 +388,7 @@ int main(int argc, char **argv) { SDL_GL_DeleteContext(glctx); SDL_DestroyWindow(window); SDL_Quit(); - buffer_free(buffer); + buffer_free(&text_buffer); text_font_free(ted->font); free(ted); #if _WIN32 @@ -82,3 +82,15 @@ static void ted_load_font(Ted *ted) { ted_seterr(ted, "Couldn't find font file. There is probably a problem with your ted installation."); } } + +static void ted_menu_open(Ted *ted, Menu menu) { + ted->menu = menu; + ted->prev_active_buffer = ted->active_buffer; + ted->active_buffer = NULL; +} + +static void ted_menu_close(Ted *ted, bool restore_prev_active_buffer) { + ted->menu = MENU_NONE; + if (restore_prev_active_buffer) ted->active_buffer = ted->prev_active_buffer; + ted->prev_active_buffer = NULL; +} @@ -51,6 +51,7 @@ PageDown = :page-down Ctrl+PageUp = 10 :page-up Ctrl+PageDown = 10 :page-down +Ctrl+o = :open Ctrl+s = :save Ctrl+z = :undo Ctrl+Shift+z = :redo @@ -65,3 +66,6 @@ cursor = #3ff selection-bg = #36aa text = #fff bg = #001 +# The entire screen gets filled with this color when a menu (e.g. the "open" menu) is shown. +# By making it transparent, we can dim everything else while the menu is open. +menu-bg = #0004 @@ -65,10 +65,19 @@ typedef struct { BufferEdit *redo_history; // dynamic array of redo history } TextBuffer; +ENUM_U16 { + MENU_NONE, + MENU_OPEN +} ENUM_U16_END(Menu); + typedef struct Ted { Font *font; TextBuffer *active_buffer; + // while a menu or something is open, there is no active buffer. when the menu is closed, + // the old active buffer needs to be restored. that's what this stores. + TextBuffer *prev_active_buffer; Settings settings; + Menu menu; KeyAction key_actions[KEY_COMBO_COUNT]; char error[256]; } Ted; |