summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-02-03 17:28:50 +0100
committerAlbert Cervin <albert@acervin.com>2023-02-03 17:28:50 +0100
commit8958e3f6c269965b19339f273dd806e985a71cde (patch)
treeef6520ae2c51d5a70fa6f71adb45488046251b4d
parentf17880d5ec783d600a3f74dff3d30acfc7d1e06c (diff)
downloaddged-8958e3f6c269965b19339f273dd806e985a71cde.tar.gz
dged-8958e3f6c269965b19339f273dd806e985a71cde.tar.xz
dged-8958e3f6c269965b19339f273dd806e985a71cde.zip
Make sure text can have 0 lines
It was a non-needed limitation
-rw-r--r--src/buffer.c39
-rw-r--r--src/minibuffer.c2
-rw-r--r--src/text.c46
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;
diff --git a/src/text.c b/src/text.c
index daa9b1a..c733af2 100644
--- a/src/text.c
+++ b/src/text.c
@@ -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 = &copy_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 = &copy_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) {