diff options
| -rw-r--r-- | src/buffer.c | 39 | ||||
| -rw-r--r-- | src/minibuffer.c | 2 | ||||
| -rw-r--r-- | src/text.c | 46 |
3 files changed, 50 insertions, 37 deletions
diff --git a/src/buffer.c b/src/buffer.c index 6af7329..6d3f3d9 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -128,8 +128,7 @@ void buffer_clear(struct buffer *buffer) { } bool buffer_is_empty(struct buffer *buffer) { - return text_num_lines(buffer->text) == 1 && - text_line_size(buffer->text, 0) == 0; + return text_num_lines(buffer->text) == 0; } uint32_t buffer_keymaps(struct buffer *buffer, struct keymap **keymaps_out) { @@ -349,12 +348,17 @@ void buffer_backward_delete_char(struct buffer *buffer) { void buffer_backward_char(struct buffer *buffer) { moveh(buffer, -1); } void buffer_forward_char(struct buffer *buffer) { moveh(buffer, 1); } -void buffer_forward_word(struct buffer *buffer) { - moveh(buffer, 1); +struct buffer_location find_next(struct buffer *buffer, uint8_t chars[], + uint32_t nchars, int direction) { struct text_chunk line = text_get_line(buffer->text, buffer->dot.line); - uint32_t bytei = + int64_t bytei = text_col_to_byteindex(buffer->text, buffer->dot.line, buffer->dot.col); - for (; bytei < line.nbytes; ++bytei) { + while (bytei < line.nbytes && bytei > 0 && + (line.text[bytei] == ' ' || line.text[bytei] == '.')) { + bytei += direction; + } + + for (; bytei < line.nbytes && bytei > 0; bytei += direction) { uint8_t b = line.text[bytei]; if (b == ' ' || b == '.') { break; @@ -363,24 +367,19 @@ void buffer_forward_word(struct buffer *buffer) { uint32_t target_col = text_byteindex_to_col(buffer->text, buffer->dot.line, bytei); - moveh(buffer, target_col - buffer->dot.col); + return (struct buffer_location){.line = buffer->dot.line, .col = target_col}; +} + +void buffer_forward_word(struct buffer *buffer) { + moveh(buffer, 1); + uint8_t chars[] = {' ', '.'}; + buffer->dot = find_next(buffer, chars, 2, 1); } void buffer_backward_word(struct buffer *buffer) { moveh(buffer, -1); - struct text_chunk line = text_get_line(buffer->text, buffer->dot.line); - uint32_t bytei = - text_col_to_byteindex(buffer->text, buffer->dot.line, buffer->dot.col); - for (; bytei > 0; --bytei) { - uint8_t b = line.text[bytei]; - if (b == ' ' || b == '.') { - break; - } - } - - uint32_t target_col = - text_byteindex_to_col(buffer->text, buffer->dot.line, bytei); - moveh(buffer, (int32_t)target_col - buffer->dot.col); + uint8_t chars[] = {' ', '.'}; + buffer->dot = find_next(buffer, chars, 2, -1); } void buffer_backward_line(struct buffer *buffer) { movev(buffer, -1); } diff --git a/src/minibuffer.c b/src/minibuffer.c index 0d7f4e5..e057262 100644 --- a/src/minibuffer.c +++ b/src/minibuffer.c @@ -150,6 +150,8 @@ void minibuffer_prompt(struct command_ctx command_ctx, const char *fmt, ...) { } minibuffer_clear(); + // make sure we have a line + buffer_add_text(g_minibuffer.buffer, (uint8_t *)"", 0); g_minibuffer.prompt_active = true; g_minibuffer.prompt_command_ctx = command_ctx; @@ -29,9 +29,7 @@ struct text *text_create(uint32_t initial_capacity) { struct text *txt = calloc(1, sizeof(struct text)); txt->lines = calloc(initial_capacity, sizeof(struct line)); txt->capacity = initial_capacity; - - // we always have one line, since add line adds a second one - txt->nlines = 1; + txt->nlines = 0; return txt; } @@ -55,7 +53,7 @@ void text_clear(struct text *text) { text->lines[li].nchars = 0; } - text->nlines = 1; + text->nlines = 0; } // given `char_idx` as a character index, return the byte index @@ -198,8 +196,7 @@ void new_line_at(struct text *text, uint32_t line, uint32_t col) { } void delete_line(struct text *text, uint32_t line) { - // always keep a single line - if (text->nlines == 1) { + if (text->nlines == 0) { return; } @@ -207,19 +204,19 @@ void delete_line(struct text *text, uint32_t line) { free(text->lines[line].data); text->lines[line].data = NULL; - shift_lines(text, line + 1, -1); - - if (text->nlines > 0) { - --text->nlines; - text->lines[text->nlines].data = NULL; - text->lines[text->nlines].nbytes = 0; - text->lines[text->nlines].nchars = 0; + if (text->nlines > 1) { + shift_lines(text, line + 1, -1); } + + --text->nlines; + text->lines[text->nlines].data = NULL; + text->lines[text->nlines].nbytes = 0; + text->lines[text->nlines].nchars = 0; } void text_append(struct text *text, uint8_t *bytes, uint32_t nbytes, uint32_t *lines_added, uint32_t *cols_added) { - uint32_t line = text->nlines - 1; + uint32_t line = text->nlines > 0 ? text->nlines - 1 : 0; uint32_t col = text_line_length(text, line); text_insert_at(text, line, col, bytes, nbytes, lines_added, cols_added); @@ -344,6 +341,24 @@ struct copy_cmd { struct text_chunk text_get_region(struct text *text, uint32_t start_line, uint32_t start_col, uint32_t end_line, uint32_t end_col) { + if (start_line == end_line && start_col == end_col) { + return (struct text_chunk){0}; + } + + struct line *first_line = &text->lines[start_line]; + struct line *last_line = &text->lines[end_line]; + + if (start_col > first_line->nchars) { + return (struct text_chunk){0}; + } + + // handle deletion of newlines + if (end_col > last_line->nchars) { + ++end_line; + end_col = 0; + last_line = &text->lines[end_line]; + } + uint32_t nlines = end_line - start_line + 1; struct copy_cmd *copy_cmds = calloc(nlines, sizeof(struct copy_cmd)); @@ -361,7 +376,6 @@ struct text_chunk text_get_region(struct text *text, uint32_t start_line, // correct first line struct copy_cmd *cmd_first = ©_cmds[0]; - struct line *first_line = &text->lines[start_line]; uint32_t byteoff = utf8_nbytes(first_line->data, first_line->nbytes, start_col); cmd_first->byteindex += byteoff; @@ -371,7 +385,6 @@ struct text_chunk text_get_region(struct text *text, uint32_t start_line, // correct last line struct copy_cmd *cmd_last = ©_cmds[nlines - 1]; - struct line *last_line = &text->lines[end_line]; uint32_t byteindex = utf8_nbytes(last_line->data, last_line->nbytes, end_col); cmd_last->nbytes -= (last_line->nchars - end_col); total_bytes -= (last_line->nbytes - byteindex); @@ -401,7 +414,6 @@ struct text_chunk text_get_region(struct text *text, uint32_t start_line, .nbytes = total_bytes, .nchars = total_chars, }; - ; } bool text_line_contains_unicode(struct text *text, uint32_t line) { |
