summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-03-05 14:38:19 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-03-05 14:38:19 -0500
commit23771a9e599700aa9c80139abb122a0f6c97976a (patch)
tree9fd67445e59e4df66a5832378ba533d6dd7c73fe
parent3afd86c471e3ae6f806737908689a20eb686360a (diff)
fix rendering if border-thickness is big
-rw-r--r--README.md5
-rw-r--r--buffer.c20
-rw-r--r--find.c38
-rw-r--r--gl.c13
-rw-r--r--main.c1
-rw-r--r--math.c9
-rw-r--r--menu.c15
-rw-r--r--node.c16
-rw-r--r--ted.c7
-rw-r--r--ted.pngbin81487 -> 75840 bytes
-rw-r--r--ui.c17
11 files changed, 92 insertions, 49 deletions
diff --git a/README.md b/README.md
index a3c421e..9b457c5 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
A text editor.
-**ted is still very new, and there are almost certainly bugs. There are also definitely important features missing. I don't recommend using this as your main text editor yet.**
+**ted is still very new, and there are almost certainly bugs. I don't recommend using this as your main text editor yet.**
<img src="ted.png">
@@ -71,7 +71,8 @@ at any time to generate tags for all files in the current directory. Once you ha
to go to its definition. You can also press Ctrl+D to get a searchable list of all functions/types where you can select one to go to
its definition. Press Ctrl+space to autocomplete. If there is only one possible completion from the tags file, it will be selected automatically.
Otherwise, you'll get a popup showing all possible completions. You can press tab to select a completion (or click on it), and press
-Ctrl+space/Ctrl+shift+space to cycle between suggestions.
+Ctrl+space/Ctrl+shift+space to cycle between suggestions. Note that autocomplete just completes to stuff in the tags file, so it won't complete local
+variable names. Sorry.
## Building from source
diff --git a/buffer.c b/buffer.c
index 51bdfbe..06f2960 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1099,6 +1099,8 @@ i64 buffer_cursor_move_right(TextBuffer *buffer, i64 by) {
i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by) {
BufferPos cur_pos = buffer->cursor_pos;
+ if (buffer->selection && buffer_pos_cmp(buffer->selection_pos, buffer->cursor_pos) < 0)
+ cur_pos = buffer->selection_pos; // go to one line above the selection pos (instead of the cursor pos) if it's before the cursor
i64 ret = buffer_pos_move_up(buffer, &cur_pos, by);
buffer_cursor_move_to_pos(buffer, cur_pos);
return ret;
@@ -1106,6 +1108,8 @@ i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by) {
i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by) {
BufferPos cur_pos = buffer->cursor_pos;
+ if (buffer->selection && buffer_pos_cmp(buffer->selection_pos, buffer->cursor_pos) > 0)
+ cur_pos = buffer->selection_pos;
i64 ret = buffer_pos_move_down(buffer, &cur_pos, by);
buffer_cursor_move_to_pos(buffer, cur_pos);
return ret;
@@ -2226,7 +2230,17 @@ void buffer_render(TextBuffer *buffer, Rect r) {
float const border_thickness = settings->border_thickness;
u32 start_line = buffer_first_rendered_line(buffer); // line to start rendering from
- Rect bounding_box = rect4(x1, y1, x2, y2);
+
+
+ u32 border_color = colors[COLOR_BORDER]; // color of border around buffer
+ // bounding box around buffer
+ gl_geometry_rect_border(rect4(x1, y1, x2, y2), border_thickness, border_color);
+
+ x1 += border_thickness;
+ y1 += border_thickness;
+ x2 -= border_thickness;
+ y2 -= border_thickness;
+
float render_start_y = y1 - (float)(buffer->scroll_y - start_line) * char_height; // where the 1st line is rendered
@@ -2304,10 +2318,6 @@ void buffer_render(TextBuffer *buffer, Rect r) {
gl_geometry_rect(hl_rect, colors[COLOR_CURSOR_LINE_BG]);
}
- u32 border_color = colors[COLOR_BORDER]; // color of border around buffer
-
- // bounding box around buffer
- gl_geometry_rect_border(bounding_box, border_thickness, border_color);
// what x coordinate to start rendering the text from
float render_start_x = x1 - (float)buffer->scroll_x * char_width;
diff --git a/find.c b/find.c
index 1e0b409..2878015 100644
--- a/find.c
+++ b/find.c
@@ -71,9 +71,11 @@ static float find_menu_height(Ted *ted) {
Font *font = ted->font;
float char_height = text_font_char_height(font);
Settings const *settings = &ted->settings;
- float padding = settings->padding;
+ float const padding = settings->padding;
+ float const border_thickness = settings->border_thickness;
+ float const line_buffer_height = ted_line_buffer_height(ted);
- return 3 * char_height + (padding + char_height) * ted->replace + 6 * padding;
+ return 3 * char_height + 4 * border_thickness + (padding + line_buffer_height) * ted->replace + 6 * padding;
}
// finds the next match in the buffer, returning false if there is no match this line.
@@ -311,13 +313,14 @@ static void find_replace_all(Ted *ted) {
static void find_menu_frame(Ted *ted, Rect menu_bounds) {
Font *font = ted->font, *font_bold = ted->font_bold;
- float const char_height = text_font_char_height(font),
- char_height_bold = text_font_char_height(font_bold);
+ float const char_height = text_font_char_height(font);
Settings const *settings = &ted->settings;
float const padding = settings->padding;
+ float const border_thickness = settings->border_thickness;
u32 const *colors = settings->colors;
bool const replace = ted->replace;
+ float const line_buffer_height = ted_line_buffer_height(ted);
TextBuffer *buffer = find_search_buffer(ted), *find_buffer = &ted->find_buffer, *replace_buffer = &ted->replace_buffer;
if (!buffer) return;
@@ -326,6 +329,10 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) {
u32 last_rendered_line = buffer_last_rendered_line(buffer);
+ gl_geometry_rect(menu_bounds, colors[COLOR_MENU_BG]);
+ gl_geometry_rect_border(menu_bounds, border_thickness, colors[COLOR_BORDER]);
+ menu_bounds = rect_shrink(menu_bounds, border_thickness);
+
float x1, y1, x2, y2;
rect_coords(menu_bounds, &x1, &y1, &x2, &y2);
@@ -336,13 +343,13 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) {
char const *prev_text = "Previous", *next_text = "Next";
char const *replace_text = "Replace", *replace_find_text = "Replace+find", *replace_all_text = "Replace all";
- v2 prev_size = text_get_size_v2(font, prev_text);
- v2 next_size = text_get_size_v2(font, next_text);
- v2 replace_size = text_get_size_v2(font, replace_text);
- v2 replace_find_size = text_get_size_v2(font, replace_find_text);
- v2 replace_all_size = text_get_size_v2(font, replace_all_text);
+ v2 prev_size = button_get_size(ted, prev_text);
+ v2 next_size = button_get_size(ted, next_text);
+ v2 replace_size = button_get_size(ted, replace_text);
+ v2 replace_find_size = button_get_size(ted, replace_find_text);
+ v2 replace_all_size = button_get_size(ted, replace_all_text);
- float x = x1, y = y2 - char_height;
+ float x = x1, y = y2 - prev_size.y;
// compute positions of buttons
Rect button_prev = rect(V2(x, y), prev_size);
x += button_prev.size.x + padding;
@@ -355,6 +362,7 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) {
Rect button_replace_all = rect(V2(x, y), replace_all_size);
x += button_replace_all.size.x + padding;
+
if (button_update(ted, button_prev))
find_next_in_direction(ted, -1);
if (button_update(ted, button_next))
@@ -387,11 +395,9 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) {
text_get_size(font_bold, replace ? replace_with_text : find_text, &text_width, NULL);
- Rect find_buffer_bounds = rect4(x1 + text_width + padding, y1, x2 - padding, y1 + char_height);
- Rect replace_buffer_bounds = rect_translate(find_buffer_bounds, V2(0, char_height + padding));
+ Rect find_buffer_bounds = rect4(x1 + text_width + padding, y1, x2 - padding, y1 + line_buffer_height);
+ Rect replace_buffer_bounds = rect_translate(find_buffer_bounds, V2(0, line_buffer_height + padding));
- gl_geometry_rect(menu_bounds, colors[COLOR_MENU_BG]);
- gl_geometry_rect_border(menu_bounds, 1, colors[COLOR_BORDER]);
button_render(ted, button_prev, prev_text, colors[COLOR_TEXT]);
button_render(ted, button_next, next_text, colors[COLOR_TEXT]);
@@ -417,11 +423,11 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) {
}
text_utf8(font_bold, find_text, x1, y1, colors[COLOR_TEXT]);
- y1 += char_height_bold + padding;
+ y1 += line_buffer_height + padding;
if (replace) {
text_utf8(font_bold, replace_with_text, x1, y1, colors[COLOR_TEXT]);
- y1 += char_height_bold + padding;
+ y1 += line_buffer_height + padding;
}
gl_geometry_draw();
diff --git a/gl.c b/gl.c
index a30eb59..a7f720f 100644
--- a/gl.c
+++ b/gl.c
@@ -210,17 +210,16 @@ static void gl_geometry_rect(Rect r, u32 color_rgba) {
}
static void gl_geometry_rect_border(Rect r, float border_thickness, u32 color) {
- float border_radius = border_thickness * 0.5f;
float x1 = r.pos.x, y1 = r.pos.y, x2 = x1 + r.size.x, y2 = y1 + r.size.y;
// make sure rectangle isn't too small
- x2 = maxf(x2, x1 + 2 * border_radius);
- y2 = maxf(y2, y1 + 2 * border_radius);
+ x2 = maxf(x2, x1 + border_thickness);
+ y2 = maxf(y2, y1 + border_thickness);
- gl_geometry_rect(rect4(x1+border_radius, y1-border_radius, x2+border_radius, y1+border_radius), color);
- gl_geometry_rect(rect4(x1-border_radius, y2-border_radius, x2-border_radius, y2+border_radius), color);
- gl_geometry_rect(rect4(x1-border_radius, y1-border_radius, x1+border_radius, y2-border_radius), color);
- gl_geometry_rect(rect4(x2-border_radius, y1+border_radius, x2+border_radius, y2+border_radius), color);
+ gl_geometry_rect(rect4(x1+border_thickness, y1, x2, y1+border_thickness), color);
+ gl_geometry_rect(rect4(x1, y2-border_thickness, x2-border_thickness, y2), color);
+ gl_geometry_rect(rect4(x1, y1, x1+border_thickness, y2), color);
+ gl_geometry_rect(rect4(x2-border_thickness, y1+border_thickness, x2, y2), color);
}
static void gl_geometry_draw(void) {
diff --git a/main.c b/main.c
index 64a79a6..356a2fa 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,4 @@
// @TODO:
-// - update screenshot in README
// - test windows 7
#include "base.h"
diff --git a/math.c b/math.c
index 75ec497..42f6cb9 100644
--- a/math.c
+++ b/math.c
@@ -748,6 +748,15 @@ static Rect rect_shrink(Rect r, float amount) {
return r;
}
+// adds `amount` to all sides of r
+static Rect rect_grow(Rect r, float amount) {
+ r.pos.x -= amount;
+ r.pos.y -= amount;
+ r.size.x += 2 * amount;
+ r.size.y += 2 * amount;
+ return r;
+}
+
static v4 color_rgba_to_hsva(v4 rgba) {
float R = rgba.x, G = rgba.y, B = rgba.z, A = rgba.w;
float M = maxf(R, maxf(G, B));
diff --git a/menu.c b/menu.c
index 975ce15..aff805a 100644
--- a/menu.c
+++ b/menu.c
@@ -312,11 +312,12 @@ static void menu_render(Ted *ted) {
assert(menu);
Settings const *settings = &ted->settings;
u32 const *colors = settings->colors;
- float window_width = ted->window_width, window_height = ted->window_height;
+ float const window_width = ted->window_width, window_height = ted->window_height;
Font *font_bold = ted->font_bold, *font = ted->font;
- float char_height = text_font_char_height(font);
- float char_height_bold = text_font_char_height(font_bold);
-
+ float const char_height = text_font_char_height(font);
+ float const char_height_bold = text_font_char_height(font_bold);
+ float const line_buffer_height = ted_line_buffer_height(ted);
+
// render backdrop
gl_geometry_rect(rect(V2(0, 0), V2(window_width, window_height)), colors[COLOR_MENU_BACKDROP]);
gl_geometry_draw();
@@ -405,8 +406,6 @@ static void menu_render(Ted *ted) {
buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y2));
} break;
case MENU_COMMAND_SELECTOR: {
- float line_buffer_height = char_height;
-
// argument field
char const *text = "Argument";
text_utf8(font_bold, text, x1, y1, colors[COLOR_TEXT]);
@@ -421,9 +420,7 @@ static void menu_render(Ted *ted) {
text_render(font_bold);
} break;
- case MENU_SHELL: {
- float line_buffer_height = char_height;
-
+ case MENU_SHELL: {
bounds.size.y = line_buffer_height + 2 * padding;
rect_coords(bounds, &x1, &y1, &x2, &y2);
diff --git a/node.c b/node.c
index be4e676..5ae0ea7 100644
--- a/node.c
+++ b/node.c
@@ -193,8 +193,8 @@ static void node_frame(Ted *ted, Node *node, Rect r) {
u32 const *colors = settings->colors;
Font *font = ted->font;
float const border_thickness = settings->border_thickness;
-
- float tab_bar_height = 20;
+ float const char_height = text_font_char_height(font);
+ float tab_bar_height = char_height + 2 * border_thickness;
Rect tab_bar_rect = r;
tab_bar_rect.size.y = tab_bar_height;
@@ -284,6 +284,12 @@ static void node_frame(Ted *ted, Node *node, Rect r) {
char const *path = buffer_get_filename(buffer);
char const *filename = path ? path_filename(path) : TED_UNTITLED;
Rect tab_rect = rect(V2(r.pos.x + tab_width * i, r.pos.y), V2(tab_width, tab_bar_height));
+
+ if (i > 0) {
+ // make sure tab borders overlap (i.e. don't double the border thickness between tabs)
+ tab_rect.pos.x -= border_thickness;
+ tab_rect.size.x += border_thickness;
+ }
if (node == ted->dragging_tab_node && i == ted->dragging_tab_idx) {
// make tab follow mouse
@@ -292,6 +298,7 @@ static void node_frame(Ted *ted, Node *node, Rect r) {
// tab border
gl_geometry_rect_border(tab_rect, border_thickness, colors[COLOR_BORDER]);
+ tab_rect = rect_shrink(tab_rect, border_thickness);
// tab title
{
@@ -324,6 +331,11 @@ static void node_frame(Ted *ted, Node *node, Rect r) {
TextBuffer *buffer = &ted->buffers[buffer_index];
assert(ted->buffers_used[buffer_index]);
Rect buffer_rect = rect_translate(r, V2(0, tab_bar_height));
+
+ // make sure buffer border and tab border overlap
+ buffer_rect.pos.y -= border_thickness;
+ buffer_rect.size.y += border_thickness;
+
buffer_rect.size.y -= tab_bar_height;
buffer_render(buffer, buffer_rect);
} else {
diff --git a/ted.c b/ted.c
index cc9eb06..3150458 100644
--- a/ted.c
+++ b/ted.c
@@ -172,6 +172,13 @@ static i32 ted_new_node(Ted *ted) {
}
+// how tall is a line buffer?
+static float ted_line_buffer_height(Ted const *ted) {
+ Settings const *settings = &ted->settings;
+ float const char_height = text_font_char_height(ted->font);
+ return char_height + 2 * settings->border_thickness;
+}
+
// switch to this node
static void ted_node_switch(Ted *ted, Node *node) {
assert(node->tabs);
diff --git a/ted.png b/ted.png
index 1f70e83..3d64d1d 100644
--- a/ted.png
+++ b/ted.png
Binary files differ
diff --git a/ui.c b/ui.c
index be3b35c..4d825d1 100644
--- a/ui.c
+++ b/ui.c
@@ -3,12 +3,10 @@
#endif
static float selector_entries_start_y(Ted const *ted, Selector const *s) {
- Font *font = ted->font;
- float char_height = text_font_char_height(font);
float padding = ted->settings.padding;
return s->bounds.pos.y
- + char_height * 1.25f + padding; // make room for line buffer
+ + ted_line_buffer_height(ted) + padding; // make room for line buffer
}
// number of entries that can be displayed on the screen
@@ -107,7 +105,6 @@ static void selector_render(Ted *ted, Selector *s) {
Settings const *settings = &ted->settings;
u32 const *colors = settings->colors;
Font *font = ted->font;
- float char_height = text_font_char_height(font);
Rect bounds = s->bounds;
@@ -127,7 +124,7 @@ static void selector_render(Ted *ted, Selector *s) {
float x1, y1, x2, y2;
rect_coords(bounds, &x1, &y1, &x2, &y2);
// search buffer
- float line_buffer_height = char_height;
+ float line_buffer_height = ted_line_buffer_height(ted);
buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y1 + line_buffer_height));
y1 += line_buffer_height;
@@ -514,6 +511,11 @@ static void file_selector_render(Ted *ted, FileSelector *fs) {
selector_render(ted, sel);
}
+static v2 button_get_size(Ted *ted, char const *text) {
+ float border_thickness = ted->settings.border_thickness;
+ return v2_add_const(text_get_size_v2(ted->font, text), 2 * border_thickness);
+}
+
static void button_render(Ted *ted, Rect button, char const *text, u32 color) {
u32 const *colors = ted->settings.colors;
@@ -643,6 +645,7 @@ static v2 checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) {
Settings const *settings = &ted->settings;
u32 const *colors = settings->colors;
float padding = settings->padding;
+ float border_thickness = settings->border_thickness;
Rect checkbox_rect = rect(pos, V2(checkbox_size, checkbox_size));
@@ -653,9 +656,9 @@ static v2 checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) {
}
checkbox_rect.pos = v2_add(checkbox_rect.pos, V2(0.5f, 0.5f));
- gl_geometry_rect_border(checkbox_rect, 1, colors[COLOR_TEXT]);
+ gl_geometry_rect_border(checkbox_rect, border_thickness, colors[COLOR_TEXT]);
if (*value) {
- gl_geometry_rect(rect_shrink(checkbox_rect, checkbox_size * 0.2f), colors[COLOR_TEXT]);
+ gl_geometry_rect(rect_shrink(checkbox_rect, border_thickness + 2), colors[COLOR_TEXT]);
}
v2 text_pos = v2_add(pos, V2(checkbox_size + padding * 0.5f, 0));