summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-12-27 21:03:11 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-12-27 21:03:11 -0500
commitc1cb1b308d65b0f3a0b7a946d5aa74ce43b30d0a (patch)
treee7bd601a1c1bb456ee594abb7de93dcc48d05ae3
parentc38e418286c5cc2e8af7f68de9483d9cdcf95dce (diff)
click to move cursor
-rw-r--r--buffer.c56
-rw-r--r--main.c13
2 files changed, 60 insertions, 9 deletions
diff --git a/buffer.c b/buffer.c
index 7f9d810..cac587e 100644
--- a/buffer.c
+++ b/buffer.c
@@ -608,6 +608,10 @@ static u32 buffer_index_to_column(TextBuffer *buffer, u32 line, u32 index) {
}
static u32 buffer_column_to_index(TextBuffer *buffer, u32 line, u32 column) {
+ if (line >= buffer->nlines) {
+ assert(0);
+ return 0;
+ }
char32_t *str = buffer->lines[line].str;
u32 len = buffer->lines[line].len;
u32 col = 0;
@@ -653,7 +657,7 @@ void buffer_text_dimensions(TextBuffer *buffer, u32 *lines, u32 *columns) {
// returns the number of rows of text that can fit in the buffer, rounded down.
-int buffer_display_rows(TextBuffer *buffer) {
+int buffer_display_lines(TextBuffer *buffer) {
return (int)((buffer->y2 - buffer->y1) / text_font_char_height(buffer->font));
}
@@ -671,7 +675,7 @@ static void buffer_correct_scroll(TextBuffer *buffer) {
u32 nlines, ncols;
buffer_text_dimensions(buffer, &nlines, &ncols);
double max_scroll_x = (double)ncols - buffer_display_cols(buffer);
- double max_scroll_y = (double)nlines - buffer_display_rows(buffer);
+ double max_scroll_y = (double)nlines - buffer_display_lines(buffer);
if (max_scroll_x <= 0) {
buffer->scroll_x = 0;
} else if (buffer->scroll_x > max_scroll_x) {
@@ -691,7 +695,7 @@ void buffer_scroll(TextBuffer *buffer, double dx, double dy) {
buffer_correct_scroll(buffer);
}
-// returns the position of the character at the given position in the buffer.
+// sets *x and *y to the position of the character at the given position in the buffer.
// x/y can be NULL.
void buffer_pos_to_pixels(TextBuffer *buffer, BufferPos pos, float *x, float *y) {
u32 line = pos.line, index = pos.index;
@@ -701,6 +705,30 @@ void buffer_pos_to_pixels(TextBuffer *buffer, BufferPos pos, float *x, float *y)
if (y) *y = (float)((double)line - buffer->scroll_y) * text_font_char_height(buffer->font) + buffer->y1;
}
+// convert pixel coordinates to a position in the buffer, selecting the closest character.
+// returns false if the position is not inside the buffer.
+bool buffer_pixels_to_pos(TextBuffer *buffer, float x, float y, BufferPos *pos) {
+ pos->line = pos->index = 0;
+
+ x -= buffer->x1;
+ y -= buffer->y1;
+ x /= text_font_char_width(buffer->font);
+ y /= text_font_char_height(buffer->font);
+ double display_col = (double)x;
+ if (display_col < 0 || display_col >= buffer_display_cols(buffer))
+ return false;
+ double display_line = (double)y;
+ if (display_line < 0 || display_line >= buffer_display_lines(buffer))
+ return false;
+
+ u32 column = (u32)round(display_col + buffer->scroll_x);
+ u32 line = (u32)floor(display_line + buffer->scroll_y);
+ u32 index = buffer_column_to_index(buffer, line, column);
+ pos->line = line;
+ pos->index = index;
+
+ return true;
+}
// clip the rectangle so it's all inside the buffer. returns true if there's any rectangle left.
static bool buffer_clip_rect(TextBuffer *buffer, float *x1, float *y1, float *x2, float *y2) {
@@ -848,7 +876,7 @@ void buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) {
static void buffer_scroll_to_cursor(TextBuffer *buffer) {
i64 cursor_line = buffer->cursor_pos.line;
i64 cursor_col = buffer_index_to_column(buffer, (u32)cursor_line, buffer->cursor_pos.index);
- i64 display_lines = buffer_display_rows(buffer);
+ i64 display_lines = buffer_display_lines(buffer);
i64 display_cols = buffer_display_cols(buffer);
double scroll_x = buffer->scroll_x, scroll_y = buffer->scroll_y;
i64 scroll_padding = 5;
@@ -871,6 +899,13 @@ static void buffer_scroll_to_cursor(TextBuffer *buffer) {
buffer_correct_scroll(buffer); // it's possible that min/max_scroll_x/y go too far
}
+// @TODO
+#if 0
+// scroll so that the cursor is in the center of the screen
+void buffer_center_cursor(){
+}
+#endif
+
// move left (if `by` is negative) or right (if `by` is positive) by the specified amount.
// returns the signed number of characters successfully moved (it could be less in magnitude than `by` if the beginning of the file is reached)
i64 buffer_pos_move_horizontally(TextBuffer *buffer, BufferPos *p, i64 by) {
@@ -1001,6 +1036,12 @@ i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by) {
return ret;
}
+void buffer_cursor_move_to_pos(TextBuffer *buffer, BufferPos pos) {
+ buffer_pos_validate(buffer, &pos);
+ buffer->cursor_pos = pos;
+ buffer_scroll_to_cursor(buffer);
+}
+
// move left / right by the specified number of words
// returns the number of words successfully moved forward
@@ -1200,8 +1241,8 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32
}
void buffer_insert_text_at_cursor(TextBuffer *buffer, String32 str) {
- buffer->cursor_pos = buffer_insert_text_at_pos(buffer, buffer->cursor_pos, str);
- buffer_scroll_to_cursor(buffer);
+ BufferPos endpos = buffer_insert_text_at_pos(buffer, buffer->cursor_pos, str);
+ buffer_cursor_move_to_pos(buffer, endpos);
}
void buffer_insert_char_at_cursor(TextBuffer *buffer, char32_t c) {
@@ -1433,7 +1474,8 @@ static Status buffer_undo_edit(TextBuffer *buffer, BufferEdit const *edit, Buffe
}
static void buffer_cursor_to_edit(TextBuffer *buffer, BufferEdit *edit) {
- buffer->cursor_pos = buffer_pos_advance(buffer, edit->pos, edit->prev_len);
+ buffer_cursor_move_to_pos(buffer,
+ buffer_pos_advance(buffer, edit->pos, edit->prev_len));
}
void buffer_undo(TextBuffer *buffer, i64 ntimes) {
diff --git a/main.c b/main.c
index 763decd..41387d1 100644
--- a/main.c
+++ b/main.c
@@ -104,13 +104,22 @@ int main(void) {
double scroll_speed = 2.5;
buffer_scroll(&text_buffer, dx * scroll_speed, dy * scroll_speed);
} break;
+ case SDL_MOUSEBUTTONDOWN:
+ switch (event.button.button) {
+ case SDL_BUTTON_LEFT: {
+ BufferPos pos;
+ if (buffer_pixels_to_pos(&text_buffer, (float)event.button.x, (float)event.button.y, &pos))
+ buffer_cursor_move_to_pos(&text_buffer, pos);
+ } break;
+ }
+ break;
case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_PAGEUP:
- buffer_scroll(&text_buffer, 0, -buffer_display_rows(&text_buffer));
+ buffer_scroll(&text_buffer, 0, -buffer_display_lines(&text_buffer));
break;
case SDLK_PAGEDOWN:
- buffer_scroll(&text_buffer, 0, +buffer_display_rows(&text_buffer));
+ buffer_scroll(&text_buffer, 0, +buffer_display_lines(&text_buffer));
break;
case SDLK_RIGHT:
if (ctrl)