summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-02-08 13:47:53 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-02-08 13:47:53 -0500
commitaa862462008e647cc4e87fd4618fe5dc5af1076d (patch)
tree76a4ca76c70b64f9b7f8be3fbf5177d4b67d476f
parent84f650da7824e1600479b54a4b75d56e9e59e06b (diff)
scroll to find match
-rw-r--r--buffer.c22
-rw-r--r--find.c34
-rw-r--r--ted.h1
3 files changed, 38 insertions, 19 deletions
diff --git a/buffer.c b/buffer.c
index b00f122..33ae6be 100644
--- a/buffer.c
+++ b/buffer.c
@@ -786,27 +786,26 @@ static bool buffer_clip_rect(TextBuffer *buffer, Rect *r) {
}
-// if the cursor is offscreen, this will scroll to make it onscreen.
-static void buffer_scroll_to_cursor(TextBuffer *buffer) {
+void buffer_scroll_to_pos(TextBuffer *buffer, BufferPos pos) {
Settings const *settings = buffer_settings(buffer);
- double cursor_line = buffer->cursor_pos.line;
- double cursor_col = buffer_index_to_column(buffer, (u32)cursor_line, buffer->cursor_pos.index);
+ double line = pos.line;
+ double col = buffer_index_to_column(buffer, pos.line, pos.index);
double display_lines = buffer_display_lines(buffer);
double display_cols = buffer_display_cols(buffer);
double scroll_x = buffer->scroll_x, scroll_y = buffer->scroll_y;
double scrolloff = settings->scrolloff;
- // scroll left if cursor is off screen in that direction
- double max_scroll_x = cursor_col - scrolloff;
+ // scroll left if pos is off screen in that direction
+ double max_scroll_x = col - scrolloff;
scroll_x = mind(scroll_x, max_scroll_x);
// scroll right
- double min_scroll_x = cursor_col - display_cols + scrolloff;
+ double min_scroll_x = col - display_cols + scrolloff;
scroll_x = maxd(scroll_x, min_scroll_x);
// scroll up
- double max_scroll_y = cursor_line - scrolloff;
+ double max_scroll_y = line - scrolloff;
scroll_y = mind(scroll_y, max_scroll_y);
// scroll down
- double min_scroll_y = cursor_line - display_lines + scrolloff;
+ double min_scroll_y = line - display_lines + scrolloff;
scroll_y = maxd(scroll_y, min_scroll_y);
buffer->scroll_x = scroll_x;
@@ -814,6 +813,11 @@ static void buffer_scroll_to_cursor(TextBuffer *buffer) {
buffer_correct_scroll(buffer); // it's possible that min/max_scroll_x/y go too far
}
+// if the cursor is offscreen, this will scroll to make it onscreen.
+void buffer_scroll_to_cursor(TextBuffer *buffer) {
+ buffer_scroll_to_pos(buffer, buffer->cursor_pos);
+}
+
// scroll so that the cursor is in the center of the screen
void buffer_center_cursor(TextBuffer *buffer) {
double cursor_line = buffer->cursor_pos.line;
diff --git a/find.c b/find.c
index 0d7b2c4..ee7793f 100644
--- a/find.c
+++ b/find.c
@@ -35,13 +35,10 @@ static void find_menu_frame(Ted *ted) {
float const menu_height = find_menu_height(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, *find_buffer = &ted->find_buffer;
assert(buffer);
-
-
String32 term = buffer_get_line(find_buffer, 0);
if (term.len) {
pcre2_match_data *match_data = pcre2_match_data_create(FIND_MAX_GROUPS, NULL);
@@ -53,6 +50,9 @@ static void find_menu_frame(Ted *ted) {
if (code) {
if (find_buffer->modified) { // if search term has been changed,
// recompute match count
+ BufferPos best_scroll_candidate = {U32_MAX, U32_MAX}; // pos we will scroll to (scroll to first match)
+ BufferPos cursor_pos = buffer->cursor_pos;
+
u32 match_count = 0;
for (u32 line_idx = 0, end = buffer->nlines; line_idx < end; ++line_idx) {
Line *line = &buffer->lines[line_idx];
@@ -62,6 +62,13 @@ static void find_menu_frame(Ted *ted) {
while (start_index < len) {
int ret = pcre2_match(code, str, len, start_index, 0, match_data, NULL);
if (ret > 0) {
+ // a match!
+
+ BufferPos match_start_pos = {.line = line_idx, .index = (u32)groups[0]};
+ if (best_scroll_candidate.line == U32_MAX
+ || (buffer_pos_cmp(best_scroll_candidate, cursor_pos) < 0 && buffer_pos_cmp(match_start_pos, cursor_pos) >= 0))
+ best_scroll_candidate = match_start_pos;
+
u32 match_end = (u32)groups[1];
++match_count;
start_index = match_end;
@@ -70,6 +77,8 @@ static void find_menu_frame(Ted *ted) {
}
ted->find_match_count = match_count;
find_buffer->modified = false;
+ if (best_scroll_candidate.line != U32_MAX)
+ buffer_scroll_to_pos(buffer, best_scroll_candidate);
}
// highlight matches
@@ -95,13 +104,16 @@ static void find_menu_frame(Ted *ted) {
}
}
pcre2_code_free(code);
+ ted->find_invalid_pattern = false;
} else {
- invalid_search_term = true;
+ ted->find_invalid_pattern = true;
}
pcre2_match_data_free(match_data);
}
- } else {
+ } else if (find_buffer->modified) {
ted->find_match_count = 0;
+ ted->find_invalid_pattern = false;
+ buffer_scroll_to_cursor(buffer);
}
@@ -126,14 +138,16 @@ static void find_menu_frame(Ted *ted) {
y1 += char_height_bold;
- if (invalid_search_term) {
- gl_geometry_rect(find_buffer_bounds, colors[COLOR_ERROR_BG] & 0xFFFFFF7F);
- }
-
gl_geometry_draw();
text_render(font_bold);
buffer_render(&ted->find_buffer, find_buffer_bounds);
+
+ if (ted->find_invalid_pattern)
+ gl_geometry_rect(find_buffer_bounds, colors[COLOR_NO] & 0xFFFFFF3F); // invalid regex
+ else if (term.len && ted->find_match_count == 0)
+ gl_geometry_rect(find_buffer_bounds, colors[COLOR_CANCEL] & 0xFFFFFF3F); // no matches
+ gl_geometry_draw();
}
diff --git a/ted.h b/ted.h
index 3694858..83c5071 100644
--- a/ted.h
+++ b/ted.h
@@ -220,6 +220,7 @@ typedef struct Ted {
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?
u32 find_match_count; // how many matches of the search term were there?
+ bool find_invalid_pattern; // invalid regex?
Command warn_unsaved; // if non-zero, the user is trying to execute this command, but there are unsaved changes
char warn_unsaved_names[TED_PATH_MAX]; // comma-separated list of files with unsaved changes (only applicable if warn_unsaved != 0)
char warn_overwrite[TED_PATH_MAX]; // file name user is trying to overwrite