summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-02-09 10:15:42 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-02-09 10:15:42 -0500
commit7be42dc83ff694da2f1e66a59a14fe51d3e18fba (patch)
treeb4da6d79dcfd52c11a1220860670ff3ac0477e01
parentf9afc00d15f934d8509f3eeb7c62b01ca84ca204 (diff)
case sensitivity, regex
-rw-r--r--find.c40
-rw-r--r--main.c2
-rw-r--r--math.c48
-rw-r--r--ted.h2
-rw-r--r--text.c7
-rw-r--r--text.h1
-rw-r--r--ui.c18
7 files changed, 81 insertions, 37 deletions
diff --git a/find.c b/find.c
index 929c253..0d3d3f4 100644
--- a/find.c
+++ b/find.c
@@ -1,6 +1,11 @@
#define FIND_MAX_GROUPS 50
-static bool find_compile_pattern(Ted *ted, bool error_on_invalid_pattern) {
+static u32 find_compilation_flags(Ted *ted) {
+ return (ted->find_case_sensitive ? 0 : PCRE2_CASELESS)
+ | (ted->find_regex ? 0 : PCRE2_LITERAL);
+}
+
+static bool find_compile_pattern(Ted *ted) {
TextBuffer *find_buffer = &ted->find_buffer;
String32 term = buffer_get_line(find_buffer, 0);
if (term.len) {
@@ -8,7 +13,7 @@ static bool find_compile_pattern(Ted *ted, bool error_on_invalid_pattern) {
if (match_data) {
int error = 0;
PCRE2_SIZE error_pos = 0;
- pcre2_code *code = pcre2_compile(term.str, term.len, PCRE2_LITERAL, &error, &error_pos, NULL);
+ pcre2_code *code = pcre2_compile(term.str, term.len, find_compilation_flags(ted), &error, &error_pos, NULL);
if (code) {
ted->find_code = code;
ted->find_match_data = match_data;
@@ -16,7 +21,8 @@ static bool find_compile_pattern(Ted *ted, bool error_on_invalid_pattern) {
return true;
} else {
ted->find_invalid_pattern = true;
- if (error_on_invalid_pattern) {
+ #if 0
+ // @TODO: write this to a buffer and check it in find_next_in_direction
char32_t buf[256] = {0};
size_t len = (size_t)pcre2_get_error_message(error, buf, sizeof buf - 1);
char *error_cstr = str32_to_utf8_cstr(str32(buf, len));
@@ -24,7 +30,7 @@ static bool find_compile_pattern(Ted *ted, bool error_on_invalid_pattern) {
ted_seterr(ted, "Invalid search term (position %zu): %s.", (size_t)error_pos, error_cstr);
free(error_cstr);
}
- }
+ #endif
}
pcre2_match_data_free(match_data);
} else {
@@ -69,7 +75,7 @@ static float find_menu_height(Ted *ted) {
Settings const *settings = &ted->settings;
float padding = settings->padding;
- return char_height + 4 * padding;
+ return 2 * char_height + 5 * padding;
}
// finds the next match in the buffer, returning false if there is no match this line.
@@ -93,11 +99,13 @@ static WarnUnusedResult bool find_match(Ted *ted, BufferPos *pos, u32 *match_sta
int next_ret = pcre2_match(ted->find_code, str.str, pos->index, last_pos, 0, ted->find_match_data, NULL);
if (next_ret > 0) {
ret = next_ret;
+ if (groups[0] == groups[1]) ++groups[1]; // ensure we don't have an infinite loop
last_pos = (u32)groups[1];
} else break;
}
}
if (ret > 0) {
+ if (groups[0] == groups[1]) ++groups[1];
if (match_start) *match_start = (u32)groups[0];
if (match_end) *match_end = (u32)groups[1];
pos->index = (u32)groups[1];
@@ -113,15 +121,19 @@ static WarnUnusedResult bool find_match(Ted *ted, BufferPos *pos, u32 *match_sta
}
}
-static void find_update(Ted *ted, bool error_on_invalid_pattern) {
+// check if the search term needs to be recompiled
+static void find_update(Ted *ted) {
TextBuffer *find_buffer = &ted->find_buffer;
- if (!find_buffer->modified) return;
-
+ u32 flags = find_compilation_flags(ted);
+ if (!find_buffer->modified // check if buffer has been modified,
+ && ted->find_flags == flags) // or checkboxes have been (un)checked
+ return;
+ ted->find_flags = flags;
TextBuffer *buffer = ted->prev_active_buffer;
find_free_pattern(ted);
- if (find_compile_pattern(ted, error_on_invalid_pattern)) {
+ if (find_compile_pattern(ted)) {
BufferPos pos = buffer_start_of_file(buffer);
BufferPos best_scroll_candidate = {U32_MAX, U32_MAX};
BufferPos cursor_pos = buffer->cursor_pos;
@@ -163,7 +175,7 @@ static void find_menu_frame(Ted *ted) {
u32 first_rendered_line = buffer_first_rendered_line(buffer);
u32 last_rendered_line = buffer_last_rendered_line(buffer);
- find_update(ted, false);
+ find_update(ted);
u32 match_pos = U32_MAX; // index of result we are on
arr_foreach_ptr(ted->find_results, FindResult, result) {
@@ -216,10 +228,14 @@ static void find_menu_frame(Ted *ted) {
}
text_utf8(font_bold, "Find...", x1, y1, colors[COLOR_TEXT]);
- y1 += char_height_bold;
+ y1 += char_height_bold + padding;
gl_geometry_draw();
text_render(font_bold);
+
+ float x = x1;
+ x += checkbox_frame(ted, &ted->find_case_sensitive, "Case sensitive", V2(x, y1)).x + 2*padding;
+ x += checkbox_frame(ted, &ted->find_regex, "Regular expression", V2(x, y1)).x + 2*padding;
buffer_render(find_buffer, find_buffer_bounds);
@@ -240,7 +256,7 @@ static void find_next_in_direction(Ted *ted, int direction) {
BufferPos pos = direction == +1 || !buffer->selection ? buffer->cursor_pos : buffer->selection_pos;
u32 nlines = buffer->nlines;
- find_update(ted, true);
+ find_update(ted);
// we need to search the starting line twice, because we might start at a non-zero index
for (size_t nsearches = 0; nsearches < nlines + 1; ++nsearches) {
diff --git a/main.c b/main.c
index 9f4b508..e5f6bb9 100644
--- a/main.c
+++ b/main.c
@@ -47,8 +47,8 @@ no_warn_end
#include "syntax.c"
#include "buffer.c"
#include "ted.c"
-#include "find.c"
#include "ui.c"
+#include "find.c"
#include "node.c"
#include "menu.c"
#include "command.c"
diff --git a/math.c b/math.c
index e6e90f3..ab7b859 100644
--- a/math.c
+++ b/math.c
@@ -607,6 +607,25 @@ static v2i V2I(int x, int y) {
return v;
}
+static void rgba_u32_to_floats(u32 rgba, float floats[4]) {
+ floats[0] = (float)((rgba >> 24) & 0xFF) / 255.f;
+ floats[1] = (float)((rgba >> 16) & 0xFF) / 255.f;
+ floats[2] = (float)((rgba >> 8) & 0xFF) / 255.f;
+ floats[3] = (float)((rgba >> 0) & 0xFF) / 255.f;
+}
+
+static v4 rgba_u32_to_v4(u32 rgba) {
+ float c[4];
+ rgba_u32_to_floats(rgba, c);
+ return V4(c[0], c[1], c[2], c[3]);
+}
+
+// returns average of red green and blue components of color
+static float rgba_brightness(u32 color) {
+ u8 r = (u8)(color >> 24), g = (u8)(color >> 16), b = (u8)(color >> 8);
+ return ((float)r+(float)g+(float)b) * (1.0f / 3);
+}
+
static bool rect_contains_point_v2(v2 pos, v2 size, v2 point) {
float x1 = pos.x, y1 = pos.y, x2 = pos.x + size.x, y2 = pos.y + size.y,
x = point.x, y = point.y;
@@ -671,24 +690,6 @@ static void rect_print(Rect r) {
printf("Position: (%f, %f), Size: (%f, %f)\n", r.pos.x, r.pos.y, r.size.x, r.size.y);
}
-static void rgba_u32_to_floats(u32 rgba, float floats[4]) {
- floats[0] = (float)((rgba >> 24) & 0xFF) / 255.f;
- floats[1] = (float)((rgba >> 16) & 0xFF) / 255.f;
- floats[2] = (float)((rgba >> 8) & 0xFF) / 255.f;
- floats[3] = (float)((rgba >> 0) & 0xFF) / 255.f;
-}
-
-static v4 rgba_u32_to_v4(u32 rgba) {
- float c[4];
- rgba_u32_to_floats(rgba, c);
- return V4(c[0], c[1], c[2], c[3]);
-}
-
-// returns average of red green and blue components of color
-static float rgba_brightness(u32 color) {
- u8 r = (u8)(color >> 24), g = (u8)(color >> 16), b = (u8)(color >> 8);
- return ((float)r+(float)g+(float)b) * (1.0f / 3);
-}
static float rects_intersect(Rect r1, Rect r2) {
if (r1.pos.x >= r2.pos.x + r2.size.x) return false; // r1 is to the right of r2
@@ -709,3 +710,14 @@ static bool rect_clip_to_rect(Rect *clipped, Rect clipper) {
clipped->size.y = clampf(clipped->size.y, 0, clipper.pos.y + clipper.size.y - clipped->pos.y);
return clipped->size.x > 0 && clipped->size.y > 0;
}
+
+// removes `amount` from all sides of r
+static Rect rect_shrink(Rect r, float amount) {
+ r.pos.x += amount;
+ r.pos.y += amount;
+ r.size.x -= 2 * amount;
+ r.size.y -= 2 * amount;
+ r.size.x = maxf(r.size.x, 0);
+ r.size.y = maxf(r.size.y, 0);
+ return r;
+} \ No newline at end of file
diff --git a/ted.h b/ted.h
index 7d7f7c7..be41ac8 100644
--- a/ted.h
+++ b/ted.h
@@ -227,6 +227,8 @@ typedef struct Ted {
bool search_cwd; // should the working directory be searched for files? set to true if the executable isn't "installed"
bool quit; // if set to true, the window will close next frame. NOTE: this doesn't check for unsaved changes!!
bool find; // is the find menu open?
+ bool find_regex, find_case_sensitive; // find options
+ u32 find_flags; // flags used last time search term was compiled
pcre2_code *find_code;
pcre2_match_data *find_match_data;
FindResult *find_results;
diff --git a/text.c b/text.c
index 074dde6..aeb17ea 100644
--- a/text.c
+++ b/text.c
@@ -374,6 +374,13 @@ void text_get_size(Font *font, char const *text, float *width, float *height) {
if (height) *height = y + font->char_height;
}
+v2 text_get_size_v2(Font *font, char const *text) {
+ v2 v;
+ text_get_size(font, text, &v.x, &v.y);
+ return v;
+}
+
+
void text_get_size32(Font *font, char32_t const *text, u64 len, float *width, float *height) {
TextRenderState render_state = text_render_state_default;
render_state.render = false;
diff --git a/text.h b/text.h
index 362516a..a60047f 100644
--- a/text.h
+++ b/text.h
@@ -53,6 +53,7 @@ extern float text_font_char_height(Font *font);
extern float text_font_char_width(Font *font);
// Get the dimensions of some text.
extern void text_get_size(Font *font, char const *text, float *width, float *height);
+extern v2 text_get_size_v2(Font *font, char const *text);
extern void text_get_size32(Font *font, char32_t const *text, u64 len, float *width, float *height);
extern void text_utf8(Font *font, char const *text, float x, float y, u32 color);
extern void text_utf8_anchored(Font *font, char const *text, float x, float y, u32 color, Anchor anchor);
diff --git a/ui.c b/ui.c
index b743d82..7640215 100644
--- a/ui.c
+++ b/ui.c
@@ -600,12 +600,14 @@ static void popup_render(Ted *ted, u32 options, char const *title, char const *b
text_render(font);
}
-static void checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) {
+// returns the size of the checkbox, including the label
+static v2 checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) {
Font *font = ted->font;
float char_height = text_font_char_height(font);
float checkbox_size = char_height;
Settings const *settings = &ted->settings;
u32 const *colors = settings->colors;
+ float padding = settings->padding;
Rect checkbox_rect = rect(pos, V2(checkbox_size, checkbox_size));
@@ -615,13 +617,17 @@ static void checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) {
}
}
- if (*value)
- gl_geometry_rect(checkbox_rect, colors[COLOR_TEXT]);
- else
- gl_geometry_rect_border(checkbox_rect, 1, colors[COLOR_TEXT]);
- v2 text_pos = v2_add(pos, V2(checkbox_size, 0));
+ checkbox_rect.pos = v2_add(checkbox_rect.pos, V2(0.5f, 0.5f));
+ gl_geometry_rect_border(checkbox_rect, 1, colors[COLOR_TEXT]);
+ if (*value) {
+ gl_geometry_rect(rect_shrink(checkbox_rect, checkbox_size * 0.2f), colors[COLOR_TEXT]);
+ }
+
+ v2 text_pos = v2_add(pos, V2(checkbox_size + padding * 0.5f, 0));
+ v2 size = text_get_size_v2(font, label);
text_utf8(font, label, text_pos.x, text_pos.y, colors[COLOR_TEXT]);
gl_geometry_draw();
text_render(font);
+ return v2_add(size, V2(checkbox_size + padding * 0.5f, 0));
}