summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--colors.h2
-rw-r--r--find.c153
-rw-r--r--main.c4
-rw-r--r--ted.cfg2
4 files changed, 108 insertions, 53 deletions
diff --git a/colors.h b/colors.h
index c37240a..1512aef 100644
--- a/colors.h
+++ b/colors.h
@@ -18,6 +18,7 @@ ENUM_U16 {
COLOR_ERROR_BG,
COLOR_ERROR_BORDER,
COLOR_ACTIVE_TAB_HL,
+ COLOR_FIND_HL,
COLOR_YES,
COLOR_NO,
@@ -62,6 +63,7 @@ static ColorName const color_names[COLOR_COUNT] = {
{COLOR_ERROR_BG, "error-bg"},
{COLOR_ERROR_BORDER, "error-border"},
{COLOR_ACTIVE_TAB_HL, "active-tab-hl"},
+ {COLOR_FIND_HL, "find-hl"},
{COLOR_KEYWORD, "keyword"},
{COLOR_BUILTIN, "builtin"},
{COLOR_COMMENT, "comment"},
diff --git a/find.c b/find.c
index 309923d..5bddd0e 100644
--- a/find.c
+++ b/find.c
@@ -1,7 +1,9 @@
static void find_open(Ted *ted) {
- ted->prev_active_buffer = ted->active_buffer;
- ted->active_buffer = &ted->find_buffer;
- ted->find = true;
+ if (ted->active_buffer) {
+ ted->prev_active_buffer = ted->active_buffer;
+ ted->active_buffer = &ted->find_buffer;
+ ted->find = true;
+ }
}
static void find_close(Ted *ted) {
@@ -19,6 +21,8 @@ static float find_menu_height(Ted *ted) {
return char_height_bold + char_height + 2 * padding;
}
+#define FIND_MAX_GROUPS 50
+
static void find_menu_frame(Ted *ted) {
Font *font = ted->font, *font_bold = ted->font_bold;
float const char_height = text_font_char_height(font),
@@ -30,75 +34,122 @@ static void find_menu_frame(Ted *ted) {
float const window_width = ted->window_width, window_height = ted->window_height;
u32 const *colors = settings->colors;
+ bool invalid_search_term = false;
+ TextBuffer *buffer = ted->prev_active_buffer;
+ assert(buffer);
+
+ String32 term = buffer_get_line(&ted->find_buffer, 0);
+ if (term.len) {
+ pcre2_match_data *match_data = pcre2_match_data_create(FIND_MAX_GROUPS, NULL);
+ if (match_data) {
+ PCRE2_SIZE *groups = pcre2_get_ovector_pointer(match_data);
+ // compile search term
+ int error = 0; PCRE2_SIZE error_pos = 0;
+ pcre2_code *code = pcre2_compile(term.str, term.len, PCRE2_LITERAL, &error, &error_pos, NULL);
+
+ // @TODO: scroll to first match
+ if (code) {
+ for (u32 line_idx = 0, nlines = buffer->nlines; line_idx < nlines; ++line_idx) {
+ Line *line = &buffer->lines[line_idx];
+ char32_t *str = line->str;
+ u32 len = line->len;
+ u32 start_index = 0;
+ while (start_index < len) {
+ int ret = pcre2_match(code, str, len, start_index, 0, match_data, NULL);
+ if (ret > 0) {
+ u32 match_start = (u32)groups[0];
+ u32 match_end = (u32)groups[1];
+ BufferPos p1 = {.line = line_idx, .index = match_start};
+ BufferPos p2 = {.line = line_idx, .index = match_end};
+ v2 pos1 = buffer_pos_to_pixels(buffer, p1);
+ v2 pos2 = buffer_pos_to_pixels(buffer, p2);
+ pos2.y += char_height;
+ gl_geometry_rect(rect4(pos1.x, pos1.y, pos2.x, pos2.y), colors[COLOR_FIND_HL]);
+ start_index = match_end;
+ } else break;
+ }
+ }
+ pcre2_code_free(code);
+ } else {
+ invalid_search_term = true;
+ }
+ pcre2_match_data_free(match_data);
+ }
+ }
+
float x1 = padding, y1 = window_height - menu_height, x2 = window_width - padding, y2 = window_height - padding;
Rect menu_bounds = rect4(x1, y1, x2, y2);
gl_geometry_rect_border(menu_bounds, 1, colors[COLOR_BORDER]);
- gl_geometry_draw();
text_utf8(font_bold, "Find...", x1 + padding, y1, colors[COLOR_TEXT]);
text_render(font_bold);
y1 += char_height_bold;
- buffer_render(&ted->find_buffer, rect4(x1 + padding, y1, x2 - padding, y1 + char_height));
+ Rect find_buffer_bounds = rect4(x1 + padding, y1, x2 - padding, y1 + char_height);
+ buffer_render(&ted->find_buffer, find_buffer_bounds);
+
+ if (invalid_search_term) {
+ gl_geometry_rect(find_buffer_bounds, colors[COLOR_ERROR_BG] & 0xFFFFFF7F);
+ }
+
+ gl_geometry_draw();
}
-#define FIND_MAX_GROUPS 100
// go to next find result
static void find_next(Ted *ted) {
TextBuffer *buffer = ted->prev_active_buffer;
- if (buffer) {
- // create match data
- pcre2_match_data *match_data = pcre2_match_data_create(FIND_MAX_GROUPS, NULL);
- if (match_data) {
- String32 term = buffer_get_line(&ted->find_buffer, 0);
- int error = 0;
- size_t error_pos = 0;
- // compile the search term
- pcre2_code *code = pcre2_compile(term.str, term.len, PCRE2_LITERAL, &error, &error_pos, NULL);
- if (code) {
- // do the searching
- BufferPos pos = buffer->cursor_pos;
- size_t nsearches = 0;
- u32 nlines = buffer->nlines;
-
- // we need to search the starting line twice, because we might start at a non-zero index
- while (nsearches < nlines + 1) {
- Line *line = &buffer->lines[pos.line];
- char32_t *str = line->str;
- size_t len = line->len;
- int ret = pcre2_match(code, str, len, pos.index, 0, match_data, NULL);
- if (ret > 0) {
- PCRE2_SIZE *groups = pcre2_get_ovector_pointer(match_data);
- u32 match_start = (u32)groups[0];
- u32 match_end = (u32)groups[1];
- BufferPos pos_start = {.line = pos.line, .index = match_start};
- BufferPos pos_end = {.line = pos.line, .index = match_end};
- buffer_cursor_move_to_pos(buffer, pos_start);
- buffer_select_to_pos(buffer, pos_end);
- break;
- }
+ // create match data
+ pcre2_match_data *match_data = pcre2_match_data_create(FIND_MAX_GROUPS, NULL);
+ if (match_data) {
+ String32 term = buffer_get_line(&ted->find_buffer, 0);
+ int error = 0;
+ PCRE2_SIZE error_pos = 0;
+ // compile the search term
+ pcre2_code *code = pcre2_compile(term.str, term.len, PCRE2_LITERAL, &error, &error_pos, NULL);
+ if (code) {
+ // do the searching
+ BufferPos pos = buffer->cursor_pos;
+ size_t nsearches = 0;
+ u32 nlines = buffer->nlines;
- ++nsearches;
- pos.index = 0;
- pos.line += 1;
- pos.line %= nlines;
- }
- } else {
- 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));
- if (error_cstr) {
- ted_seterr(ted, "Invalid search term: (at position %zu) %s.", (size_t)error_pos, error_cstr);
- free(error_cstr);
+ // we need to search the starting line twice, because we might start at a non-zero index
+ while (nsearches < nlines + 1) {
+ Line *line = &buffer->lines[pos.line];
+ char32_t *str = line->str;
+ size_t len = line->len;
+ int ret = pcre2_match(code, str, len, pos.index, 0, match_data, NULL);
+ if (ret > 0) {
+ PCRE2_SIZE *groups = pcre2_get_ovector_pointer(match_data);
+ u32 match_start = (u32)groups[0];
+ u32 match_end = (u32)groups[1];
+ BufferPos pos_start = {.line = pos.line, .index = match_start};
+ BufferPos pos_end = {.line = pos.line, .index = match_end};
+ buffer_cursor_move_to_pos(buffer, pos_start);
+ buffer_select_to_pos(buffer, pos_end);
+ break;
}
+
+ ++nsearches;
+ pos.index = 0;
+ pos.line += 1;
+ pos.line %= nlines;
}
- pcre2_match_data_free(match_data);
+ pcre2_code_free(code);
} else {
- ted_seterr(ted, "Out of memory.");
+ 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));
+ if (error_cstr) {
+ ted_seterr(ted, "Invalid search term (position %zu): %s.", (size_t)error_pos, error_cstr);
+ free(error_cstr);
+ }
}
+ pcre2_match_data_free(match_data);
+ } else {
+ ted_seterr(ted, "Out of memory.");
}
}
diff --git a/main.c b/main.c
index 0090071..e8d41b4 100644
--- a/main.c
+++ b/main.c
@@ -569,12 +569,12 @@ int main(int argc, char **argv) {
if (ted->active_node) {
float x1 = 25, y1 = 25, x2 = window_width-25, y2 = window_height-25;
+ Node *node = ted->root;
+ node_frame(ted, node, rect4(x1, y1, x2, y2));
if (ted->find) {
find_menu_frame(ted);
if (ted->find) y2 -= find_menu_height(ted);
}
- Node *node = ted->root;
- node_frame(ted, node, rect4(x1, y1, x2, y2));
} else {
text_utf8_anchored(font, "Press Ctrl+O to open a file or Ctrl+N to create a new one.",
window_width * 0.5f, window_height * 0.5f, colors[COLOR_TEXT_SECONDARY], ANCHOR_MIDDLE);
diff --git a/ted.cfg b/ted.cfg
index 305246a..26e7052 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -131,6 +131,8 @@ menu-hl = #afa2
error-border = #f00
error-bg = #800
error-text = #fdd
+# color to highlight search results with
+find-hl = #fff3
yes = #afa
no = #faa
cancel = #ffa