summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c93
-rw-r--r--main.c14
-rw-r--r--node.c2
-rw-r--r--session.c2
-rw-r--r--ted.c2
-rw-r--r--ted.h68
6 files changed, 100 insertions, 81 deletions
diff --git a/buffer.c b/buffer.c
index 56afffc..cfebcac 100644
--- a/buffer.c
+++ b/buffer.c
@@ -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 {
diff --git a/main.c b/main.c
index fa02a41..898ebe4 100644
--- a/main.c
+++ b/main.c
@@ -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) {
diff --git a/node.c b/node.c
index e06664f..0eb529a 100644
--- a/node.c
+++ b/node.c
@@ -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));
diff --git a/session.c b/session.c
index 6202a08..4d01fe9 100644
--- a/session.c
+++ b/session.c
@@ -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);
diff --git a/ted.c b/ted.c
index 6893e8b..13e01a8 100644
--- a/ted.c
+++ b/ted.c
@@ -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);
diff --git a/ted.h b/ted.h
index 81e2637..d6ece2c 100644
--- a/ted.h
+++ b/ted.h
@@ -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);