From 7ba80aaa38c95fdb84cd8fb51d51b5d897c5de95 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Tue, 19 Jan 2021 10:22:52 -0500 Subject: opening files by clicking on them --- buffer.c | 7 ++++--- colors.h | 4 +++- command.c | 13 +++++-------- main.c | 32 +++++++++++++++++++++++++++----- menu.c | 43 +++++++++++++++++++++++++++++++++++++------ ted-base.c | 20 ++++++++++++++++++++ ted.cfg | 1 + ted.h | 3 +++ util.c | 4 ---- 9 files changed, 100 insertions(+), 27 deletions(-) diff --git a/buffer.c b/buffer.c index 477a1c9..9481236 100644 --- a/buffer.c +++ b/buffer.c @@ -74,7 +74,7 @@ static char *buffer_strdup(TextBuffer *buffer, char const *src) { } void buffer_create(TextBuffer *buffer, Ted *ted) { - util_zero_memory(buffer, sizeof *buffer); + memset(buffer, 0, sizeof *buffer); buffer->store_undo_events = true; buffer->ted = ted; } @@ -459,7 +459,7 @@ void buffer_free(TextBuffer *buffer) { arr_free(buffer->undo_history); arr_free(buffer->redo_history); - util_zero_memory(buffer, sizeof *buffer); + memset(buffer, 0, sizeof *buffer); } // clear contents, undo history, etc. of a buffer @@ -474,6 +474,7 @@ void buffer_clear(TextBuffer *buffer) { } else { buffer_create(buffer, ted); } + memcpy(buffer->error, error, sizeof error); } void buffer_load_file(TextBuffer *buffer, char const *filename) { @@ -1128,7 +1129,7 @@ static Status buffer_insert_lines(TextBuffer *buffer, u32 where, u32 number) { buffer->lines + where, (old_nlines - where) * sizeof *buffer->lines); // zero new lines - util_zero_memory(buffer->lines + where, number * sizeof *buffer->lines); + memset(buffer->lines + where, 0, number * sizeof *buffer->lines); buffer->nlines = new_nlines; return true; } diff --git a/colors.h b/colors.h index d51d7e7..b09fcc1 100644 --- a/colors.h +++ b/colors.h @@ -9,6 +9,7 @@ ENUM_U16 { COLOR_SELECTION_BG, COLOR_MENU_BACKDROP, COLOR_MENU_BG, + COLOR_MENU_HL, COLOR_COUNT } ENUM_U16_END(ColorSetting); @@ -27,7 +28,8 @@ static ColorName const color_names[COLOR_COUNT] = { {COLOR_TEXT, "text"}, {COLOR_SELECTION_BG, "selection-bg"}, {COLOR_MENU_BACKDROP, "menu-backdrop"}, - {COLOR_MENU_BG, "menu-bg"} + {COLOR_MENU_BG, "menu-bg"}, + {COLOR_MENU_HL, "menu-hl"} }; static ColorSetting color_setting_from_str(char const *str) { diff --git a/command.c b/command.c index 9bd58bc..206274a 100644 --- a/command.c +++ b/command.c @@ -156,16 +156,13 @@ void command_execute(Ted *ted, Command c, i64 argument) { assert(0); break; case MENU_OPEN: { - TextBuffer *open_to = &ted->main_buffer; char *filename_cstr = str32_to_utf8_cstr(buffer_get_line(&ted->line_buffer, 0)); if (filename_cstr) { - buffer_load_file(open_to, filename_cstr); - buffer = open_to; - if (buffer_haserr(open_to)) { - // @TODO: something - } + buffer = ted_open_file(ted, filename_cstr); free(filename_cstr); - menu_close(ted, true); + menu_close(ted, false); + } else { + ted_seterr(ted, "Out of memory."); } } break; } @@ -174,7 +171,7 @@ void command_execute(Ted *ted, Command c, i64 argument) { } if (buffer && buffer_haserr(buffer)) { - strncpy(ted->error, buffer_geterr(buffer), sizeof ted->error - 1); + ted_seterr_to_buferr(ted, buffer); buffer_clearerr(buffer); } } diff --git a/main.c b/main.c index 3c05744..bfbeac2 100644 --- a/main.c +++ b/main.c @@ -235,10 +235,17 @@ int main(int argc, char **argv) { SDL_Event event; Uint8 const *keyboard_state = SDL_GetKeyboardState(NULL); - + + { // get mouse position + int mouse_x = 0, mouse_y = 0; + SDL_GetMouseState(&mouse_x, &mouse_y); + ted->mouse_pos = V2((float)mouse_x, (float)mouse_y); + } bool ctrl_down = keyboard_state[SDL_SCANCODE_LCTRL] || keyboard_state[SDL_SCANCODE_RCTRL]; bool shift_down = keyboard_state[SDL_SCANCODE_LSHIFT] || keyboard_state[SDL_SCANCODE_RSHIFT]; bool alt_down = keyboard_state[SDL_SCANCODE_LALT] || keyboard_state[SDL_SCANCODE_RALT]; + + memset(ted->nmouse_clicks, 0, sizeof ted->nmouse_clicks); while (SDL_PollEvent(&event)) { TextBuffer *buffer = ted->active_buffer; @@ -256,12 +263,20 @@ int main(int argc, char **argv) { 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_MOUSEBUTTONDOWN: { + Uint32 button = event.button.button; + float x = (float)event.button.x, y = (float)event.button.y; + if (button < arr_count(ted->nmouse_clicks) + && ted->nmouse_clicks[button] < arr_count(ted->mouse_clicks[button])) { + v2 *v = &ted->mouse_clicks[button][ted->nmouse_clicks[button]++]; + v->x = x; + v->y = y; + } + switch (button) { case SDL_BUTTON_LEFT: { if (buffer) { BufferPos pos = {0}; - if (buffer_pixels_to_pos(buffer, V2((float)event.button.x, (float)event.button.y), &pos)) { + if (buffer_pixels_to_pos(buffer, V2(x, y), &pos)) { if (key_modifier == KEY_MODIFIER_SHIFT) { buffer_select_to_pos(buffer, pos); } else if (key_modifier == 0) { @@ -280,7 +295,7 @@ int main(int argc, char **argv) { } } break; } - break; + } break; case SDL_MOUSEMOTION: if (event.motion.state == SDL_BUTTON_LMASK) { if (buffer) { @@ -327,6 +342,7 @@ int main(int argc, char **argv) { } if (ted_haserr(ted)) { + // @TODO: better error handling die("%s", ted_geterr(ted)); } } @@ -389,6 +405,12 @@ int main(int argc, char **argv) { menu_render(ted, menu); } + if (ted_haserr(ted)) { + // @TODO: better error handling + die("%s", ted_geterr(ted)); + } + + #if DEBUG buffer_check_valid(&ted->main_buffer); buffer_check_valid(&ted->line_buffer); diff --git a/menu.c b/menu.c index 7c09d53..d82eb4a 100644 --- a/menu.c +++ b/menu.c @@ -54,10 +54,15 @@ static void menu_render(Ted *ted, Menu menu) { rect_render_border(menu_rect, settings->border_thickness); glEnd(); + menu_x1 += inner_padding; + menu_y1 += inner_padding; + menu_x2 -= inner_padding; + menu_y2 -= inner_padding; + float line_buffer_height = char_height * 1.5f; - float line_buffer_x1 = menu_x1 + inner_padding, - line_buffer_y1 = menu_y1 + inner_padding, - line_buffer_x2 = menu_x2 - inner_padding, + float line_buffer_x1 = menu_x1, + line_buffer_y1 = menu_y1, + line_buffer_x2 = menu_x2, line_buffer_y2 = line_buffer_y1 + line_buffer_height; buffer_render(&ted->line_buffer, line_buffer_x1, line_buffer_y1, line_buffer_x2, line_buffer_y2); @@ -80,21 +85,47 @@ static void menu_render(Ted *ted, Menu menu) { } qsort(files, nfiles, sizeof *files, str_qsort_case_insensitive_cmp); - + char const *file_to_open = NULL; { // render file names - float x = menu_x1 + inner_padding, y = menu_y1 + line_buffer_height + inner_padding; + float start_x = menu_x1, start_y = line_buffer_y2 + inner_padding; + float x = start_x, y = start_y; + + for (u32 i = 0; i < nfiles; ++i) { + // highlight entry user is mousing over + if (y >= menu_y2) break; + Rect r = rect4(x, y, menu_x2, minf(y + char_height, menu_y2)); + y += char_height; + if (rect_contains_point(r, ted->mouse_pos)) { + glBegin(GL_QUADS); + gl_color_rgba(colors[COLOR_MENU_HL]); + rect_render(r); + glEnd(); + } + for (u32 c = 0; c < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++c) { + if (rect_contains_point(r, ted->mouse_clicks[SDL_BUTTON_LEFT][c])) { + // this file got clicked on! + file_to_open = files[i]; + } + } + } + x = start_x, y = start_y; TextRenderState text_render_state = {.min_x = menu_x1, .max_x = menu_x2, .min_y = menu_y1, .max_y = menu_y2, .render = true}; gl_color_rgba(colors[COLOR_TEXT]); for (u32 i = 0; i < nfiles; ++i) { + if (y >= menu_y2) break; text_render_with_state(font, &text_render_state, files[i], x, y); y += char_height; } } + if (file_to_open) { + ted_open_file(ted, file_to_open); + menu_close(ted, false); + } + for (u32 i = 0; i < nfiles; ++i) free(files[i]); free(files); } free(search_term); } - } diff --git a/ted-base.c b/ted-base.c index e00a70a..2eac197 100644 --- a/ted-base.c +++ b/ted-base.c @@ -2,6 +2,12 @@ #define ted_seterr(buffer, ...) \ snprintf(ted->error, sizeof ted->error - 1, __VA_ARGS__) +void ted_seterr_to_buferr(Ted *ted, TextBuffer *buffer) { + size_t size = sizeof ted->error; + if (sizeof buffer->error < size) size = sizeof buffer->error; + memcpy(ted->error, buffer->error, size); +} + bool ted_haserr(Ted *ted) { return ted->error[0] != '\0'; } @@ -80,5 +86,19 @@ static void ted_load_font(Ted *ted) { } } +// returns buffer of new file +static TextBuffer *ted_open_file(Ted *ted, char const *filename) { + TextBuffer *open_to = &ted->main_buffer; + buffer_load_file(open_to, filename); + if (buffer_haserr(open_to)) { + // @TODO: something + ted_seterr_to_buferr(ted, open_to); + return NULL; + } else { + ted->active_buffer = open_to; + return open_to; + } +} + static void menu_open(Ted *ted, Menu menu); static void menu_close(Ted *ted, bool restore_prev_active_buffer); diff --git a/ted.cfg b/ted.cfg index 11bfabc..2591f43 100644 --- a/ted.cfg +++ b/ted.cfg @@ -74,3 +74,4 @@ bg = #001 # By making it transparent, we can dim everything else while the menu is open. menu-backdrop = #0004 menu-bg = #222 +menu-hl = #888 \ No newline at end of file diff --git a/ted.h b/ted.h index 36602cf..af1a2ae 100644 --- a/ted.h +++ b/ted.h @@ -82,6 +82,9 @@ typedef struct Ted { TextBuffer *prev_active_buffer; Settings settings; float window_width, window_height; + v2 mouse_pos; + u8 nmouse_clicks[4]; // nmouse_clicks[i] = length of mouse_clicks[i] + v2 mouse_clicks[4][32]; // mouse_clicks[SDL_BUTTON_RIGHT], for example, is all the right mouse-clicks that have happened this frame Menu menu; TextBuffer line_buffer; // general-purpose line buffer for inputs -- used for menus TextBuffer main_buffer; diff --git a/util.c b/util.c index 1d6bb79..8c1239c 100644 --- a/util.c +++ b/util.c @@ -15,10 +15,6 @@ static bool util_is_power_of_2(u64 x) { return util_popcount(x) == 1; } -static void util_zero_memory(void *mem, size_t size) { - memset(mem, 0, size); -} - // for finding a character in a char32 string static char32_t *util_mem32chr(char32_t *s, char32_t c, size_t n) { for (size_t i = 0; i < n; ++i) { -- cgit v1.2.3