summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-01-29 21:53:37 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-01-29 21:53:37 -0500
commit3cc173dd38e85c751bb1a9f9288ebe974e567ba4 (patch)
treefa822005135b515307c223e3154c9b03f61203d7
parent90ffcaad047caa55e65a6bf858a7b976e062007a (diff)
ctrl+pageup/down to switch between tabs
-rw-r--r--command.c12
-rw-r--r--main.c95
-rw-r--r--node.c104
-rw-r--r--ted-base.c2
-rw-r--r--ted.h3
5 files changed, 117 insertions, 99 deletions
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;