diff options
-rw-r--r-- | buffer.c | 93 | ||||
-rw-r--r-- | main.c | 14 | ||||
-rw-r--r-- | node.c | 2 | ||||
-rw-r--r-- | session.c | 2 | ||||
-rw-r--r-- | ted.c | 2 | ||||
-rw-r--r-- | ted.h | 68 |
6 files changed, 100 insertions, 81 deletions
@@ -7,25 +7,25 @@ // this is a macro so we get -Wformat warnings -#define buffer_seterr(buffer, ...) \ +#define buffer_error(buffer, ...) \ snprintf(buffer->error, sizeof buffer->error - 1, __VA_ARGS__) -bool buffer_haserr(TextBuffer *buffer) { +bool buffer_has_error(TextBuffer *buffer) { return buffer->error[0] != '\0'; } // returns the buffer's last error -const char *buffer_geterr(TextBuffer *buffer) { +const char *buffer_get_error(TextBuffer *buffer) { return buffer->error; } -void buffer_clearerr(TextBuffer *buffer) { +void buffer_clear_error(TextBuffer *buffer) { *buffer->error = '\0'; } // set the buffer's error to indicate that we're out of memory static void buffer_out_of_mem(TextBuffer *buffer) { - buffer_seterr(buffer, "Out of memory."); + buffer_error(buffer, "Out of memory."); } @@ -60,10 +60,6 @@ bool buffer_empty(TextBuffer *buffer) { return buffer->nlines == 1 && buffer->lines[0].len == 0; } -const char *buffer_get_filename(TextBuffer *buffer) { - return buffer->filename; -} - bool buffer_is_untitled(TextBuffer *buffer) { if (buffer->filename) return streq(buffer->filename, TED_UNTITLED); @@ -179,31 +175,20 @@ bool buffer_unsaved_changes(TextBuffer *buffer) { return arr_len(buffer->undo_history) != buffer->undo_history_write_pos; } -// code point at position. -// returns 0 if the position is invalid. note that it can also return 0 for a valid position, if there's a null character there -char32_t buffer_char_at_pos(TextBuffer *buffer, BufferPos p) { - if (p.line >= buffer->nlines) - return 0; // invalid (line too large) - - Line *line = &buffer->lines[p.line]; - if (p.index < line->len) { - return line->str[p.index]; - } else if (p.index > line->len) { - // invalid (col too large) +char32_t buffer_char_at_pos(TextBuffer *buffer, BufferPos pos) { + if (!buffer_pos_valid(buffer, pos)) return 0; - } else { - return '\n'; - } + + Line *line = &buffer->lines[pos.line]; + return line->str[pos.index]; } -// returns 0 if pos is at the start of a line char32_t buffer_char_before_pos(TextBuffer *buffer, BufferPos pos) { assert(buffer_pos_valid(buffer, pos)); if (pos.index == 0) return 0; return buffer->lines[pos.line].str[pos.index - 1]; } -// returns 0 if pos is at the end of a line (unlike buffer_char_at_pos) char32_t buffer_char_after_pos(TextBuffer *buffer, BufferPos pos) { assert(buffer_pos_valid(buffer, pos)); Line *line = &buffer->lines[pos.line]; @@ -211,12 +196,10 @@ char32_t buffer_char_after_pos(TextBuffer *buffer, BufferPos pos) { return line->str[pos.index]; } -// returns the character to the left of the cursor, or 0 if the cursor at the start of the line. char32_t buffer_char_before_cursor(TextBuffer *buffer) { return buffer_char_before_pos(buffer, buffer->cursor_pos); } -// returns 0 if cursor is at end of line char32_t buffer_char_after_cursor(TextBuffer *buffer) { return buffer_char_after_pos(buffer, buffer->cursor_pos); } @@ -345,10 +328,6 @@ static u64 buffer_checksum(TextBuffer *buffer) { return sum; } -// Get some number of characters of text from the given position in the buffer. -// Returns the number of characters gotten. -// You can pass NULL for text if you just want to know how many characters *could* be accessed before the -// end of the file. size_t buffer_get_text_at_pos(TextBuffer *buffer, BufferPos pos, char32_t *text, size_t nchars) { if (!buffer_pos_valid(buffer, pos)) { return 0; // invalid position. no chars for you! @@ -381,8 +360,6 @@ size_t buffer_get_text_at_pos(TextBuffer *buffer, BufferPos pos, char32_t *text, return nchars - chars_left; } -// returns a UTF-32 string of at most `nchars` code points from `buffer` starting at `pos` -// the string should be str32_free'd. String32 buffer_get_str32_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars) { String32 s32 = {0}; size_t len = buffer_get_text_at_pos(buffer, pos, NULL, nchars); @@ -397,8 +374,6 @@ String32 buffer_get_str32_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t return s32; } -// see buffer_get_str32_text_at_pos. returns NULL on failure (out of memory) -// the returned string should be free'd char *buffer_get_utf8_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars) { String32 s32 = buffer_get_str32_text_at_pos(buffer, pos, nchars); char *ret = str32_to_utf8_cstr(s32); @@ -407,9 +382,6 @@ char *buffer_get_utf8_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t ncha return ret; } -// Puts a UTF-8 string containing the contents of the buffer into out. -// Returns the number of bytes, including a null terminator. -// To use, first pass NULL for out to get the number of bytes you need to allocate. size_t buffer_contents_utf8(TextBuffer *buffer, char *out) { char *p = out, x[4]; size_t size = 0; @@ -431,8 +403,6 @@ size_t buffer_contents_utf8(TextBuffer *buffer, char *out) { return size; } -// Returns a UTF-8 string containing the contents of `buffer`. -// free the return value. char *buffer_contents_utf8_alloc(TextBuffer *buffer) { size_t size = buffer_contents_utf8(buffer, NULL); char *s = calloc(1, size); @@ -537,7 +507,6 @@ static bool buffer_line_valid(Line *line) { return true; } -// perform a series of checks to make sure the buffer doesn't have any invalid values void buffer_check_valid(TextBuffer *buffer) { assert(buffer->nlines); buffer_pos_check_valid(buffer, buffer->cursor_pos); @@ -847,8 +816,6 @@ static u32 buffer_column_to_index(TextBuffer *buffer, u32 line, u32 column) { return len; } -// returns the number of lines of text in the buffer into *lines (if not NULL), -// and the number of columns of text, i.e. the number of columns in the longest line displayed, into *cols (if not NULL) void buffer_text_dimensions(TextBuffer *buffer, u32 *lines, u32 *columns) { if (lines) { *lines = buffer->nlines; @@ -865,12 +832,10 @@ void buffer_text_dimensions(TextBuffer *buffer, u32 *lines, u32 *columns) { } -// returns the number of rows of text that can fit in the buffer float buffer_display_lines(TextBuffer *buffer) { return (buffer->y2 - buffer->y1) / text_font_char_height(buffer_font(buffer)); } -// returns the number of columns of text that can fit in the buffer float buffer_display_cols(TextBuffer *buffer) { return (buffer->x2 - buffer->x1) / text_font_char_width(buffer_font(buffer)); } @@ -905,7 +870,6 @@ 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. vec2 buffer_pos_to_pixels(TextBuffer *buffer, BufferPos pos) { buffer_pos_validate(buffer, &pos); u32 line = pos.line, index = pos.index; @@ -917,8 +881,6 @@ vec2 buffer_pos_to_pixels(TextBuffer *buffer, BufferPos pos) { return Vec2(x, y); } -// convert pixel coordinates to a position in the buffer, selecting the closest character. -// returns false if the position is not inside the buffer, but still sets *pos to the closest character. bool buffer_pixels_to_pos(TextBuffer *buffer, vec2 pixel_coords, BufferPos *pos) { bool ret = true; float x = pixel_coords.x, y = pixel_coords.y; @@ -1005,7 +967,6 @@ void buffer_scroll_to_pos(TextBuffer *buffer, BufferPos pos) { buffer_correct_scroll(buffer); // it's possible that min/max_scroll_x/y go too far } -// scroll in such a way that this position is in the center of the screen void buffer_scroll_center_pos(TextBuffer *buffer, BufferPos pos) { double line = pos.line; double col = buffer_index_to_column(buffer, pos.line, pos.index); @@ -1551,7 +1512,7 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 if (buffer->view_only) return pos; if (str.len > U32_MAX) { - buffer_seterr(buffer, "Inserting too much text (length: %zu).", str.len); + buffer_error(buffer, "Inserting too much text (length: %zu).", str.len); BufferPos ret = {0,0}; return ret; } @@ -1840,7 +1801,7 @@ static void buffer_delete_lines(TextBuffer *buffer, u32 first_line_idx, u32 nlin void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_) { if (buffer->view_only) return; if (nchars_ < 0) { - buffer_seterr(buffer, "Deleting negative characters (specifically, " I64_FMT ").", nchars_); + buffer_error(buffer, "Deleting negative characters (specifically, " I64_FMT ").", nchars_); return; } if (nchars_ <= 0) return; @@ -2247,7 +2208,7 @@ void buffer_copy_or_cut(TextBuffer *buffer, bool cut) { int err = SDL_SetClipboardText(text); free(text); if (err < 0) { - buffer_seterr(buffer, "Couldn't set clipboard contents: %s", SDL_GetError()); + buffer_error(buffer, "Couldn't set clipboard contents: %s", SDL_GetError()); } else { // text copied successfully if (cut) { @@ -2302,10 +2263,10 @@ Status buffer_load_file(TextBuffer *buffer, const char *filename) { u32 max_file_size_view_only = default_settings->max_file_size_view_only; if (file_pos == -1 || file_pos == LONG_MAX) { - buffer_seterr(buffer, "Couldn't get file position. There is something wrong with the file '%s'.", filename); + buffer_error(buffer, "Couldn't get file position. There is something wrong with the file '%s'.", filename); success = false; } else if (file_size > max_file_size_editable && file_size > max_file_size_view_only) { - buffer_seterr(buffer, "File too big (size: %zu).", file_size); + buffer_error(buffer, "File too big (size: %zu).", file_size); success = false; } else { u8 *file_contents = buffer_calloc(buffer, 1, file_size + 2); @@ -2335,7 +2296,7 @@ Status buffer_load_file(TextBuffer *buffer, const char *filename) { } else if (n >= (size_t)(-2)) { // invalid UTF-8 success = false; - buffer_seterr(buffer, "Invalid UTF-8 (position: %td).", p - file_contents); + buffer_error(buffer, "Invalid UTF-8 (position: %td).", p - file_contents); break; } else { p += n; @@ -2351,7 +2312,7 @@ Status buffer_load_file(TextBuffer *buffer, const char *filename) { } } } else { - buffer_seterr(buffer, "Error reading from file."); + buffer_error(buffer, "Error reading from file."); success = false; } if (!success) { @@ -2394,7 +2355,7 @@ Status buffer_load_file(TextBuffer *buffer, const char *filename) { } fclose(fp); } else { - buffer_seterr(buffer, "Couldn't open file %s: %s.", filename, strerror(errno)); + buffer_error(buffer, "Couldn't open file %s: %s.", filename, strerror(errno)); success = false; } return success; @@ -2422,7 +2383,7 @@ void buffer_reload(TextBuffer *buffer) { // has this buffer been changed by another program since last save? bool buffer_externally_changed(TextBuffer *buffer) { - if (!buffer->filename || buffer_is_untitled(buffer)) + if (!buffer_is_named_file(buffer)) return false; return buffer->last_write_time != timespec_to_seconds(time_last_modified(buffer->filename)); } @@ -2444,7 +2405,7 @@ bool buffer_save(TextBuffer *buffer) { if (!buffer->is_line_buffer && buffer->filename) { if (buffer->view_only) { - buffer_seterr(buffer, "Can't save view-only file."); + buffer_error(buffer, "Can't save view-only file."); return false; } @@ -2467,7 +2428,7 @@ bool buffer_save(TextBuffer *buffer) { size_t bytes = unicode_utf32_to_utf8(utf8, *p); if (bytes != (size_t)-1) { if (fwrite(utf8, 1, bytes, out) != bytes) { - buffer_seterr(buffer, "Couldn't write to %s.", buffer->filename); + buffer_error(buffer, "Couldn't write to %s.", buffer->filename); } } } @@ -2477,15 +2438,15 @@ bool buffer_save(TextBuffer *buffer) { } } if (ferror(out)) { - if (!buffer_haserr(buffer)) - buffer_seterr(buffer, "Couldn't write to %s.", buffer->filename); + if (!buffer_has_error(buffer)) + buffer_error(buffer, "Couldn't write to %s.", buffer->filename); } if (fclose(out) != 0) { - if (!buffer_haserr(buffer)) - buffer_seterr(buffer, "Couldn't close file %s.", buffer->filename); + if (!buffer_has_error(buffer)) + buffer_error(buffer, "Couldn't close file %s.", buffer->filename); } buffer->last_write_time = timespec_to_seconds(time_last_modified(buffer->filename)); - bool success = !buffer_haserr(buffer); + bool success = !buffer_has_error(buffer); if (success) { buffer->undo_history_write_pos = arr_len(buffer->undo_history); const char *name = buffer->filename ? path_filename(buffer->filename) : TED_UNTITLED; @@ -2495,7 +2456,7 @@ bool buffer_save(TextBuffer *buffer) { } return success; } else { - buffer_seterr(buffer, "Couldn't open file %s for writing: %s.", buffer->filename, strerror(errno)); + buffer_error(buffer, "Couldn't open file %s for writing: %s.", buffer->filename, strerror(errno)); return false; } } else { @@ -519,8 +519,8 @@ int main(int argc, char **argv) { { TextBuffer *lbuffer = &ted->line_buffer; line_buffer_create(lbuffer, ted); - if (buffer_haserr(lbuffer)) - die("Error creating line buffer: %s", buffer_geterr(lbuffer)); + if (buffer_has_error(lbuffer)) + die("Error creating line buffer: %s", buffer_get_error(lbuffer)); } line_buffer_create(&ted->find_buffer, ted); line_buffer_create(&ted->replace_buffer, ted); @@ -768,8 +768,8 @@ int main(int argc, char **argv) { { // ted->cwd should be the directory containing the last active buffer TextBuffer *buffer = ted->active_buffer; if (buffer) { - const char *buffer_path = buffer_get_filename(buffer); - if (buffer_path && !buffer_is_untitled(buffer)) { + if (buffer_is_named_file(buffer)) { + const char *buffer_path = buffer->filename; assert(*buffer_path); char *last_sep = strrchr(buffer_path, PATH_SEPARATOR); if (last_sep) { @@ -790,7 +790,7 @@ int main(int argc, char **argv) { if (buffer_settings(active_buffer)->auto_reload) buffer_reload(active_buffer); else { - strbuf_cpy(ted->ask_reload, buffer_get_filename(active_buffer)); + strbuf_cpy(ted->ask_reload, active_buffer->filename); menu_open(ted, MENU_ASK_RELOAD); } } @@ -988,9 +988,9 @@ int main(int argc, char **argv) { } for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) { TextBuffer *buffer = &ted->buffers[i]; - if (buffer_haserr(buffer)) { + if (buffer_has_error(buffer)) { ted_error_from_buffer(ted, buffer); - buffer_clearerr(buffer); + buffer_clear_error(buffer); } } for (int i = 0; ted->lsps[i]; ++i) { @@ -293,7 +293,7 @@ void node_frame(Ted *ted, Node *node, Rect r) { for (u16 i = 0; i < ntabs; ++i) { TextBuffer *buffer = &ted->buffers[node->tabs[i]]; char tab_title[256]; - const char *path = buffer_get_filename(buffer); + const char *path = buffer->filename; const char *filename = path ? path_filename(path) : TED_UNTITLED; Rect tab_rect = rect(Vec2(r.pos.x + tab_width * i, r.pos.y), Vec2(tab_width, tab_bar_height)); @@ -230,7 +230,7 @@ static void session_read_buffer(Ted *ted, FILE *fp) { char filename[TED_PATH_MAX] = {0}; read_cstr(fp, filename, sizeof filename); buffer_create(buffer, ted); - if (!buffer_haserr(buffer)) { + if (!buffer_has_error(buffer)) { if (*filename) { if (!buffer_load_file(buffer, filename)) buffer_new_file(buffer, TED_UNTITLED); @@ -460,7 +460,7 @@ bool ted_new_file(Ted *ted, const char *filename) { if (ted_open_buffer(ted, &buffer_idx, &tab_idx)) { TextBuffer *buffer = &ted->buffers[buffer_idx]; buffer_new_file(buffer, TED_UNTITLED); - if (!buffer_haserr(buffer)) { + if (!buffer_has_error(buffer)) { return true; } else { ted_error_from_buffer(ted, buffer); @@ -662,71 +662,129 @@ typedef struct Ted { } Ted; // === buffer.c === -bool buffer_haserr(TextBuffer *buffer); -const char *buffer_geterr(TextBuffer *buffer); -void buffer_clearerr(TextBuffer *buffer); +bool buffer_has_error(TextBuffer *buffer); +const char *buffer_get_error(TextBuffer *buffer); +void buffer_clear_error(TextBuffer *buffer); +// clear undo and redo history void buffer_clear_undo_redo(TextBuffer *buffer); +// is this buffer empty? bool buffer_empty(TextBuffer *buffer); -const char *buffer_get_filename(TextBuffer *buffer); +// is this buffer normal (i.e. not a line buffer or build buffer), but untitled? bool buffer_is_untitled(TextBuffer *buffer); +// does this buffer contained a named file (i.e. not a line buffer, not the build buffer, not untitled) bool buffer_is_named_file(TextBuffer *buffer); +// create a new empty buffer with no file name void buffer_create(TextBuffer *buffer, Ted *ted); +// create a new empty line buffer void line_buffer_create(TextBuffer *buffer, Ted *ted); +// does this buffer have unsaved changes? bool buffer_unsaved_changes(TextBuffer *buffer); -char32_t buffer_char_at_pos(TextBuffer *buffer, BufferPos p); +// returns the character at position pos, or 0 if pos is invalid +char32_t buffer_char_at_pos(TextBuffer *buffer, BufferPos pos); +// returns the character before position pos, or 0 if pos is invalid or at the start of a line char32_t buffer_char_before_pos(TextBuffer *buffer, BufferPos pos); +// returns the character after position pos, or 0 if pos is invalid or at the end of a line char32_t buffer_char_after_pos(TextBuffer *buffer, BufferPos pos); +// returns the character to the left of the cursor, or 0 if the cursor at the start of the line. char32_t buffer_char_before_cursor(TextBuffer *buffer); +// returns the character to the right of the cursor, 0 if cursor is at end of line char32_t buffer_char_after_cursor(TextBuffer *buffer); +// buffer position of start of file BufferPos buffer_pos_start_of_file(TextBuffer *buffer); +// buffer position of end of file BufferPos buffer_pos_end_of_file(TextBuffer *buffer); // ensures that `p` refers to a valid position, moving it if needed. void buffer_pos_validate(TextBuffer *buffer, BufferPos *p); +// is this a valid buffer position? bool buffer_pos_valid(TextBuffer *buffer, BufferPos p); Language buffer_language(TextBuffer *buffer); // clip the rectangle so it's all inside the buffer. returns true if there's any rectangle left. bool buffer_clip_rect(TextBuffer *buffer, Rect *r); +// get LSP server which deals with this buffer LSP *buffer_lsp(TextBuffer *buffer); // Get the settings used for this buffer. Settings *buffer_settings(TextBuffer *buffer); // NOTE: this string will be invalidated when the line is edited!!! // only use it briefly!! String32 buffer_get_line(TextBuffer *buffer, u32 line_number); +// get at most `nchars` characters starting from position `pos`. +// returns the number of characters actually available. +// you can pass NULL for text if you just want to know how many +// characters *could* be accessed before the end of the file. size_t buffer_get_text_at_pos(TextBuffer *buffer, BufferPos pos, char32_t *text, size_t nchars); +// returns a UTF-32 string of at most `nchars` code points from `buffer` starting at `pos` +// the string should be passed to str32_free. String32 buffer_get_str32_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars); +// get UTF-8 string at position, up to `nchars` code points (NOT bytes). +// the resulting string should be freed. char *buffer_get_utf8_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars); +// Puts a UTF-8 string containing the contents of the buffer into out. +// Returns the number of bytes, including a null terminator. +// To use this function, first pass NULL for out to get the number of bytes you need to allocate. size_t buffer_contents_utf8(TextBuffer *buffer, char *out); +// Returns a UTF-8 string containing the contents of `buffer`. +// The return value should be freed.. char *buffer_contents_utf8_alloc(TextBuffer *buffer); +// perform a series of checks to make sure the buffer doesn't have any invalid values void buffer_check_valid(TextBuffer *buffer); +// free all resources used by the buffer void buffer_free(TextBuffer *buffer); +// clear buffer contents void buffer_clear(TextBuffer *buffer); +// returns the number of lines of text in the buffer into *lines (if not NULL), +// and the number of columns of text, i.e. the number of columns in the longest line displayed, into *cols (if not NULL) void buffer_text_dimensions(TextBuffer *buffer, u32 *lines, u32 *columns); +// returns the number of rows of text that can fit in the buffer float buffer_display_lines(TextBuffer *buffer); +// returns the number of columns of text that can fit in the buffer float buffer_display_cols(TextBuffer *buffer); void buffer_scroll(TextBuffer *buffer, double dx, double dy); +// returns the screen position of the character at the given position in the buffer. vec2 buffer_pos_to_pixels(TextBuffer *buffer, BufferPos pos); +// convert pixel coordinates to a position in the buffer, selecting the closest character. +// returns false if the position is not inside the buffer, but still sets *pos to the closest character. bool buffer_pixels_to_pos(TextBuffer *buffer, vec2 pixel_coords, BufferPos *pos); +// scroll to `pos`, scrolling as little as possible while maintaining scrolloff. void buffer_scroll_to_pos(TextBuffer *buffer, BufferPos pos); +// scroll in such a way that this position is in the center of the screen void buffer_scroll_center_pos(TextBuffer *buffer, BufferPos pos); void buffer_scroll_to_cursor(TextBuffer *buffer); +// scroll so that the cursor is in the center of the buffer's rectangle. void buffer_center_cursor(TextBuffer *buffer); +// returns the number of characters successfully moved by. i64 buffer_pos_move_left(TextBuffer *buffer, BufferPos *pos, i64 by); +// returns the number of characters successfully moved by. i64 buffer_pos_move_right(TextBuffer *buffer, BufferPos *pos, i64 by); +// returns the number of lines successfully moved by. i64 buffer_pos_move_up(TextBuffer *buffer, BufferPos *pos, i64 by); +// returns the number of lines successfully moved by. i64 buffer_pos_move_down(TextBuffer *buffer, BufferPos *pos, i64 by); void buffer_cursor_move_to_pos(TextBuffer *buffer, BufferPos pos); +// returns the number of characters successfully moved by. i64 buffer_cursor_move_left(TextBuffer *buffer, i64 by); +// returns the number of characters successfully moved by. i64 buffer_cursor_move_right(TextBuffer *buffer, i64 by); +// returns the number of lines successfully moved by. i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by); +// returns the number of lines successfully moved by. i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by); +// returns the number of blank lines successfully moved by. i64 buffer_pos_move_up_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by); +// returns the number of blank lines successfully moved by. i64 buffer_pos_move_down_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by); +// returns the number of blank lines successfully moved by. i64 buffer_cursor_move_up_blank_lines(TextBuffer *buffer, i64 by); +// returns the number of blank lines successfully moved by. i64 buffer_cursor_move_down_blank_lines(TextBuffer *buffer, i64 by); +// returns the number of words successfully moved by. i64 buffer_pos_move_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); +// returns the number of words successfully moved by. i64 buffer_pos_move_left_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); +// returns the number of words successfully moved by. i64 buffer_pos_move_right_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); +// returns the number of words successfully moved by. i64 buffer_cursor_move_left_words(TextBuffer *buffer, i64 nwords); +// returns the number of words successfully moved by. i64 buffer_cursor_move_right_words(TextBuffer *buffer, i64 nwords); String32 buffer_word_at_pos(TextBuffer *buffer, BufferPos pos); String32 buffer_word_at_cursor(TextBuffer *buffer); |