diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-12-27 21:03:11 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-12-27 21:03:11 -0500 |
commit | c1cb1b308d65b0f3a0b7a946d5aa74ce43b30d0a (patch) | |
tree | e7bd601a1c1bb456ee594abb7de93dcc48d05ae3 | |
parent | c38e418286c5cc2e8af7f68de9483d9cdcf95dce (diff) |
click to move cursor
-rw-r--r-- | buffer.c | 56 | ||||
-rw-r--r-- | main.c | 13 |
2 files changed, 60 insertions, 9 deletions
@@ -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) { @@ -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) |