From 3cc173dd38e85c751bb1a9f9288ebe974e567ba4 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 29 Jan 2021 21:53:37 -0500 Subject: ctrl+pageup/down to switch between tabs --- command.c | 12 ++++--- main.c | 95 ++----------------------------------------------------- node.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ted-base.c | 2 +- ted.h | 3 +- 5 files changed, 117 insertions(+), 99 deletions(-) create mode 100644 node.c diff --git a/command.c b/command.c index 1c5f28b..5c7cfe0 100644 --- a/command.c +++ b/command.c @@ -145,7 +145,7 @@ void command_execute(Ted *ted, Command c, i64 argument) { break; case CMD_SAVE: if (buffer) { - if (buffer->filename && streq(buffer->filename, "Untitled")) { + if (buffer->filename && streq(buffer->filename, TED_UNTITLED)) { // don't worry, this won't catch files called "Untitled"; buffer->filename is the full path. goto save_as; } @@ -171,9 +171,6 @@ void command_execute(Ted *ted, Command c, i64 argument) { if (buffer) buffer_cut(buffer); break; case CMD_PASTE: - // @TEST @TODO: delete me - ted_seterr(ted, "Very long test error the quick brown fox jumps over the lazy dog. ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz. Thank you very much. It was the best of times. It was the worst of times. It was the age of reason. It was the age of foolishness."); - if (buffer) buffer_paste(buffer); break; @@ -191,6 +188,13 @@ void command_execute(Ted *ted, Command c, i64 argument) { ted_load_fonts(ted); } } break; + + case CMD_TAB_NEXT: + node_tab_next(ted, ted->active_node, argument); + break; + case CMD_TAB_PREV: + node_tab_prev(ted, ted->active_node, argument); + break; case CMD_ESCAPE: if (*ted->error_shown) { diff --git a/main.c b/main.c index dfe314b..7cb7f06 100644 --- a/main.c +++ b/main.c @@ -44,6 +44,7 @@ no_warn_end #include "buffer.c" #include "ted-base.c" #include "ui.c" +#include "node.c" #include "command.c" #include "config.c" #include "menu.c" @@ -74,98 +75,6 @@ static Rect error_box_rect(Ted *ted) { V2(menu_get_width(ted), 3 * char_height + 2 * padding)); } -static void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index) { - node->active_tab = new_tab_index; - if (node == ted->active_node) { - // switch active buffer - assert(node->tabs); - u16 buffer_idx = node->tabs[new_tab_index]; - ted->active_buffer = &ted->buffers[buffer_idx]; - } -} - -static void node_frame(Ted *ted, Node *node, Rect r) { - if (node->tabs) { - bool is_active = node == ted->active_node; - Settings const *settings = &ted->settings; - u32 const *colors = settings->colors; - Font *font = ted->font; - - u16 buffer_index = node->tabs[node->active_tab]; - float tab_bar_height = 20; - - Rect tab_bar_rect = r; - tab_bar_rect.size.y = tab_bar_height; - - { // tab bar - u16 ntabs = (u16)arr_len(node->tabs); - float tab_width = r.size.x / ntabs; - for (u16 c = 0; c < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++c) { - v2 click = ted->mouse_clicks[SDL_BUTTON_LEFT][c]; - if (rect_contains_point(tab_bar_rect, click)) { - u16 tab_index = (u16)((click.x - r.pos.x) / tab_width); - node_switch_to_tab(ted, node, tab_index); - } - } - for (u16 i = 0; i < ntabs; ++i) { - TextBuffer *buffer = &ted->buffers[node->tabs[i]]; - char tab_title[256]; - char const *path = buffer_get_filename(buffer); - char const *filename = path_filename(path); - Rect tab_rect = rect(V2(r.pos.x + tab_width * i, r.pos.y), V2(tab_width, tab_bar_height)); - glBegin(GL_QUADS); - gl_color_rgba(colors[COLOR_BORDER]); - - // tab border - rect_render_border(tab_rect, 1); - if (i == node->active_tab) { - // highlight active tab - gl_color_rgba(colors[is_active ? COLOR_ACTIVE_TAB_HL : COLOR_HL]); - rect_render(tab_rect); - } - glEnd(); - - // tab title - { - char const *surround = buffer_unsaved_changes(buffer) ? "*" : ""; - strbuf_printf(tab_title, "%s%s%s", surround, filename, surround); - } - gl_color_rgba(colors[COLOR_TEXT]); - TextRenderState text_state = text_render_state_default; - text_state.max_x = rect_x2(tab_rect); - text_render_with_state(font, &text_state, tab_title, tab_rect.pos.x, tab_rect.pos.y); - - } - } - - TextBuffer *buffer = &ted->buffers[buffer_index]; - Rect buffer_rect = rect_translate(r, V2(0, tab_bar_height)); - buffer_render(buffer, buffer_rect); - } else { - -#if 0 - // @TODO: test this - // this node is a split - Node *a = &ted->nodes[node->split_a]; - Node *b = &ted->nodes[node->split_b]; - Rect r1 = r, r2 = r; - if (node->vertical_split) { - float split_pos = r.size.y * node->split_pos; - r1.size.y = split_pos; - r2.pos.y += split_pos; - r2.size.y = r.size.y - split_pos; - } else { - float split_pos = r.size.x * node->split_pos; - r1.size.x = split_pos; - r2.pos.x += split_pos; - r2.size.x = r.size.x - split_pos; - } - node_render(ted, a, r1); - node_render(ted, b, r2); -#endif - } -} - #if _WIN32 INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) { @@ -191,7 +100,7 @@ int main(int argc, char **argv) { setlocale(LC_ALL, ""); // allow unicode // read command-line arguments - char const *starting_filename = "Untitled"; + char const *starting_filename = TED_UNTITLED; switch (argc) { case 0: case 1: break; case 2: diff --git a/node.c b/node.c new file mode 100644 index 0000000..6681a84 --- /dev/null +++ b/node.c @@ -0,0 +1,104 @@ +static void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index) { + node->active_tab = new_tab_index; + if (node == ted->active_node) { + // switch active buffer + assert(node->tabs); + u16 buffer_idx = node->tabs[new_tab_index]; + ted->active_buffer = &ted->buffers[buffer_idx]; + } +} + +// move n tabs to the right +static void node_tab_next(Ted *ted, Node *node, i64 n) { + assert(node->tabs); + u16 ntabs = (u16)arr_len(node->tabs); + u16 tab_idx = (u16)mod_i64(node->active_tab + n, ntabs); + node_switch_to_tab(ted, node, tab_idx); +} + +static void node_tab_prev(Ted *ted, Node *node, i64 n) { + node_tab_next(ted, node, -n); +} + +static void node_frame(Ted *ted, Node *node, Rect r) { + if (node->tabs) { + bool is_active = node == ted->active_node; + Settings const *settings = &ted->settings; + u32 const *colors = settings->colors; + Font *font = ted->font; + + u16 buffer_index = node->tabs[node->active_tab]; + float tab_bar_height = 20; + + Rect tab_bar_rect = r; + tab_bar_rect.size.y = tab_bar_height; + + { // tab bar + u16 ntabs = (u16)arr_len(node->tabs); + float tab_width = r.size.x / ntabs; + for (u16 c = 0; c < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++c) { + v2 click = ted->mouse_clicks[SDL_BUTTON_LEFT][c]; + if (rect_contains_point(tab_bar_rect, click)) { + u16 tab_index = (u16)((click.x - r.pos.x) / tab_width); + node_switch_to_tab(ted, node, tab_index); + } + } + for (u16 i = 0; i < ntabs; ++i) { + TextBuffer *buffer = &ted->buffers[node->tabs[i]]; + char tab_title[256]; + char const *path = buffer_get_filename(buffer); + char const *filename = path_filename(path); + Rect tab_rect = rect(V2(r.pos.x + tab_width * i, r.pos.y), V2(tab_width, tab_bar_height)); + glBegin(GL_QUADS); + gl_color_rgba(colors[COLOR_BORDER]); + + // tab border + rect_render_border(tab_rect, 1); + if (i == node->active_tab) { + // highlight active tab + gl_color_rgba(colors[is_active ? COLOR_ACTIVE_TAB_HL : COLOR_HL]); + rect_render(tab_rect); + } + glEnd(); + + // tab title + { + char const *surround = buffer_unsaved_changes(buffer) ? "*" : ""; + strbuf_printf(tab_title, "%s%s%s", surround, filename, surround); + } + gl_color_rgba(colors[COLOR_TEXT]); + TextRenderState text_state = text_render_state_default; + text_state.max_x = rect_x2(tab_rect); + text_render_with_state(font, &text_state, tab_title, tab_rect.pos.x, tab_rect.pos.y); + + } + } + + TextBuffer *buffer = &ted->buffers[buffer_index]; + Rect buffer_rect = rect_translate(r, V2(0, tab_bar_height)); + buffer_render(buffer, buffer_rect); + } else { + +#if 0 + // @TODO: test this + // this node is a split + Node *a = &ted->nodes[node->split_a]; + Node *b = &ted->nodes[node->split_b]; + Rect r1 = r, r2 = r; + if (node->vertical_split) { + float split_pos = r.size.y * node->split_pos; + r1.size.y = split_pos; + r2.pos.y += split_pos; + r2.size.y = r.size.y - split_pos; + } else { + float split_pos = r.size.x * node->split_pos; + r1.size.x = split_pos; + r2.pos.x += split_pos; + r2.size.x = r.size.x - split_pos; + } + node_render(ted, a, r1); + node_render(ted, b, r2); +#endif + } +} + diff --git a/ted-base.c b/ted-base.c index 4cc1bee..8b0ab07 100644 --- a/ted-base.c +++ b/ted-base.c @@ -148,7 +148,7 @@ static void ted_new_file(Ted *ted) { arr_add(node->tabs, (u16)new_buffer_index); TextBuffer *new_buffer = &ted->buffers[new_buffer_index]; if (node->tabs) { - buffer_new_file(new_buffer, "Untitled"); + buffer_new_file(new_buffer, TED_UNTITLED); if (!buffer_haserr(new_buffer)) { ted->active_buffer = new_buffer; node->active_tab = (u16)(arr_len(node->tabs) - 1); diff --git a/ted.h b/ted.h index 30abb4b..d589365 100644 --- a/ted.h +++ b/ted.h @@ -1,4 +1,5 @@ #define TED_PATH_MAX 256 +#define TED_UNTITLED "Untitled" // what to call untitled buffers #define TEXT_SIZE_MIN 6 #define TEXT_SIZE_MAX 70 @@ -70,7 +71,7 @@ typedef struct { u32 nlines; u32 lines_capacity; Line *lines; - char error[128]; + char error[256]; BufferEdit *undo_history; // dynamic array of undo history BufferEdit *redo_history; // dynamic array of redo history } TextBuffer; -- cgit v1.2.3