diff options
-rw-r--r-- | buffer.c | 43 | ||||
-rw-r--r-- | main.c | 83 | ||||
-rw-r--r-- | ted.h | 6 | ||||
-rw-r--r-- | text.c | 14 | ||||
-rw-r--r-- | text.h | 7 | ||||
-rw-r--r-- | ui.c | 12 |
6 files changed, 112 insertions, 53 deletions
@@ -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; @@ -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); } } @@ -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 @@ -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]); } @@ -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 @@ -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]); |