summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c43
-rw-r--r--main.c83
-rw-r--r--ted.h6
-rw-r--r--text.c14
-rw-r--r--text.h7
-rw-r--r--ui.c12
6 files changed, 112 insertions, 53 deletions
diff --git a/buffer.c b/buffer.c
index 381d7a7..11b1b6c 100644
--- a/buffer.c
+++ b/buffer.c
@@ -48,6 +48,10 @@ bool buffer_empty(TextBuffer *buffer) {
return buffer->nlines == 1 && buffer->lines[0].len == 0;
}
+char const *buffer_get_filename(TextBuffer *buffer) {
+ return buffer->filename;
+}
+
// clear all undo and redo events
void buffer_clear_undo_redo(TextBuffer *buffer) {
buffer_clear_undo_history(buffer);
@@ -1834,7 +1838,9 @@ void buffer_check_valid(TextBuffer *buffer) {
#endif
// Render the text buffer in the given rectangle
-void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) {
+void buffer_render(TextBuffer *buffer, Rect r) {
+ float x1, y1, x2, y2;
+ rect_coords(r, &x1, &y1, &x2, &y2);
// Correct the scroll, because the window size might have changed
buffer_correct_scroll(buffer);
@@ -1843,7 +1849,6 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) {
Line *lines = buffer->lines;
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 const *settings = buffer_settings(buffer);
@@ -1875,40 +1880,6 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) {
.render = true
};
-
- if (!buffer->is_line_buffer) { // header
- glColor3f(1,1,1);
- float x = x1, y = y1;
- if (buffer->filename) {
- char text[256] = {0};
- strbuf_printf(text, "%s%s%s", buffer->modified ? "*" : "", buffer->filename, buffer->modified ? "*" :"");
- text_render_with_state(font, &text_state, text, x, y);
- }
- #if DEBUG
- // show checksum
- char checksum[32] = {0};
- snprintf(checksum, sizeof checksum - 1, "%08llx", (ullong)buffer_checksum(buffer));
- gl_color1f(0.5f);
- float checksum_w = 0;
- text_get_size(font, checksum, &checksum_w, NULL);
- x = x2 - checksum_w;
- text_render_with_state(font, &text_state, checksum, x, y);
- #endif
-
- y1 += header_height + 0.5f * border_thickness;
-
- // line separating header from buffer proper
- glBegin(GL_QUADS);
- gl_color_rgba(border_color);
- glVertex2f(x1, y1 - 0.5f * border_thickness);
- glVertex2f(x2, y1 - 0.5f * border_thickness);
- glVertex2f(x2, y1 + 0.5f * border_thickness);
- glVertex2f(x1, y1 + 0.5f * border_thickness);
- glEnd();
- y1 += 0.5f * border_thickness;
- }
-
-
buffer->x1 = x1; buffer->y1 = y1; buffer->x2 = x2; buffer->y2 = y2;
diff --git a/main.c b/main.c
index 686a515..0ad9672 100644
--- a/main.c
+++ b/main.c
@@ -73,6 +73,73 @@ static Rect error_box_rect(Ted *ted) {
V2(menu_get_width(ted), 3 * char_height + 2 * padding));
}
+static void node_render(Ted *ted, Node *node, Rect r) {
+ if (node->tabs) {
+ 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 i = 0; i < ntabs; ++i) {
+ TextBuffer *buffer = &ted->buffers[node->tabs[i]];
+ char tab_title[256];
+ char const *filename = buffer_get_filename(buffer);
+ 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);
+ 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 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) {
@@ -465,10 +532,7 @@ int main(int argc, char **argv) {
{
float x1 = 50, y1 = 50, x2 = window_width-50, y2 = window_height-50;
Node *node = ted->active_node;
- buffer_render(&ted->buffers[node->tabs[node->active_tab]], x1, y1, x2, y2);
- if (text_has_err()) {
- ted_seterr(ted, "Couldn't render text: %s", text_get_err());
- }
+ node_render(ted, node, rect4(x1, y1, x2, y2));
}
Menu menu = ted->menu;
@@ -476,6 +540,10 @@ int main(int argc, char **argv) {
menu_render(ted, menu);
}
+
+ if (text_has_err()) {
+ ted_seterr(ted, "Couldn't render text: %s", text_get_err());
+ }
for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) {
TextBuffer *buffer = &ted->buffers[i];
if (buffer_haserr(buffer)) {
@@ -526,9 +594,10 @@ int main(int argc, char **argv) {
float text_y1 = rect_y1(r) + padding;
// (make sure text wraps)
- TextRenderState text_state = {.x = text_x1, .y = text_y1,
- .min_x = text_x1, .max_x = text_x2, .min_y = -FLT_MAX, .max_y = FLT_MAX,
- .render = true, .wrap = true};
+ TextRenderState text_state = text_render_state_default;
+ text_state.min_x = text_x1;
+ text_state.max_x = text_x2;
+ text_state.wrap = true;
text_render_with_state(font, &text_state, ted->error_shown, text_x1, text_y1);
}
}
diff --git a/ted.h b/ted.h
index 9228d00..30abb4b 100644
--- a/ted.h
+++ b/ted.h
@@ -103,9 +103,11 @@ typedef struct {
// a node is a collection of tabs OR a split of two nodes
typedef struct Node {
u16 *tabs; // dynamic array of indices into ted->buffers, or NULL if this is a split
+ float split_pos; // number from 0 to 1 indicating where the split is.
u16 active_tab;
- u16 left; // index into ted->nodes
- u16 right;
+ bool vertical_split; // is the split vertical? if false, this split looks like a|b
+ u16 split_a; // split left/upper half; index into ted->nodes
+ u16 split_b; // split right/lower half
} Node;
#define TED_MAX_BUFFERS 256
diff --git a/text.c b/text.c
index 70bd3d4..7bafd14 100644
--- a/text.c
+++ b/text.c
@@ -25,6 +25,14 @@ struct Font {
int curr_page;
};
+TextRenderState const text_render_state_default = {
+ .render = true,
+ .wrap = false,
+ .x = 0, .y = 0,
+ .min_x = -FLT_MAX, .max_x = +FLT_MAX,
+ .min_y = -FLT_MAX, .max_y = +FLT_MAX
+};
+
static char text_err[200];
void text_clear_err(void) {
text_err[0] = '\0';
@@ -270,7 +278,8 @@ void text_render_with_state(Font *font, TextRenderState *render_state, char cons
}
static void text_render_internal(Font *font, char const *text, float *x, float *y, bool render) {
- TextRenderState render_state = {.x = 0, .y = 0, .min_x = -FLT_MAX, .max_x = FLT_MAX, .min_y = -FLT_MAX, .max_y = FLT_MAX, .render = render};
+ TextRenderState render_state = text_render_state_default;
+ render_state.render = render;
text_render_with_state(font, &render_state, text, *x, *y);
*x = render_state.x;
*y = render_state.y;
@@ -306,7 +315,8 @@ void text_get_size(Font *font, char const *text, float *width, float *height) {
}
void text_get_size32(Font *font, char32_t const *text, u64 len, float *width, float *height) {
- TextRenderState render_state = {.x = 0, .y = 0, .min_x = -FLT_MAX, .max_x = FLT_MAX, .min_y = -FLT_MAX, .max_y = FLT_MAX, .render = false};
+ TextRenderState render_state = text_render_state_default;
+ render_state.render = false;
for (u64 i = 0; i < len; ++i) {
text_render_char(font, &render_state, text[i]);
}
diff --git a/text.h b/text.h
index 0232f42..b0629b9 100644
--- a/text.h
+++ b/text.h
@@ -61,4 +61,11 @@ extern void text_render_char(Font *font, TextRenderState *state, char32_t c);
// Free memory used by font.
extern void text_font_free(Font *font);
+// The "default" text rendering state - everything you need to just render text normally.
+// This lets you do stuff like:
+// TextRenderState state = text_render_state_default;
+// (set a few options)
+// text_render_with_state(font, &state, ...)
+extern TextRenderState const text_render_state_default;
+
#endif
diff --git a/ui.c b/ui.c
index f0cdb72..e49e9c1 100644
--- a/ui.c
+++ b/ui.c
@@ -431,7 +431,7 @@ static void file_selector_render(Ted *ted, FileSelector *fs) {
// search buffer
float line_buffer_height = char_height * 1.5f;
- buffer_render(&ted->line_buffer, x1, y1, x2, y1 + line_buffer_height);
+ buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y1 + line_buffer_height));
y1 += line_buffer_height;
@@ -577,11 +577,11 @@ static void popup_render(Ted *ted, char const *title, char const *body) {
gl_color_rgba(colors[COLOR_TEXT]);
float text_x1 = rect_x1(r) + padding;
float text_x2 = rect_x2(r) - padding;
- TextRenderState state = {
- .render = true, .wrap = true,
- .min_x = text_x1, .max_x = text_x2,
- .min_y = -FLT_MAX, .max_y = +FLT_MAX
- };
+
+ TextRenderState state = text_render_state_default;
+ state.min_x = text_x1;
+ state.max_x = text_x2;
+ state.wrap = true;
text_render_with_state(font, &state, body, text_x1, y);
button_render(ted, button_yes, "Yes", colors[COLOR_YES]);