diff options
| -rw-r--r-- | src/dged/buffer.c | 21 | ||||
| -rw-r--r-- | src/dged/text.c | 17 | ||||
| -rw-r--r-- | src/dged/text.h | 7 |
3 files changed, 41 insertions, 4 deletions
diff --git a/src/dged/buffer.c b/src/dged/buffer.c index e428c58..d03f3ad 100644 --- a/src/dged/buffer.c +++ b/src/dged/buffer.c @@ -1,5 +1,6 @@ #include "buffer.h" #include "binding.h" +#include "dged/text.h" #include "dged/vec.h" #include "display.h" #include "errno.h" @@ -237,7 +238,7 @@ static void buffer_read_from_file(struct buffer *b) { undo_push_boundary(&b->undo, (struct undo_boundary){.save_point = true}); } -static void write_line(struct text_chunk *chunk, void *userdata) { +static void write_line_lf(struct text_chunk *chunk, void *userdata) { FILE *file = (FILE *)userdata; fwrite(chunk->text, 1, chunk->nbytes, file); @@ -245,6 +246,15 @@ static void write_line(struct text_chunk *chunk, void *userdata) { fputc('\n', file); } +static void write_line_crlf(struct text_chunk *chunk, void *userdata) { + FILE *file = (FILE *)userdata; + fwrite(chunk->text, 1, chunk->nbytes, file); + + // final newline is not optional! + fputc('\r', file); + fputc('\n', file); +} + static bool is_word_break(const struct codepoint *codepoint) { uint32_t c = codepoint->codepoint; return c == ' ' || c == '.' || c == '(' || c == ')' || c == '[' || c == ']' || @@ -417,7 +427,14 @@ void buffer_to_file(struct buffer *buffer) { if (nlines > 0) { struct text_chunk lastline = text_get_line(buffer->text, nlines - 1); nlines_to_write = lastline.nbytes == 0 ? nlines - 1 : nlines; - text_for_each_line(buffer->text, 0, nlines_to_write, write_line, file); + switch (text_get_line_ending(buffer->text)) { + case LineEnding_CRLF: + text_for_each_line(buffer->text, 0, nlines_to_write, write_line_crlf, + file); + break; + default: + text_for_each_line(buffer->text, 0, nlines_to_write, write_line_lf, file); + } } minibuffer_echo_timeout(4, "wrote %d lines to %s", nlines_to_write, diff --git a/src/dged/text.c b/src/dged/text.c index e609557..59290ca 100644 --- a/src/dged/text.c +++ b/src/dged/text.c @@ -38,6 +38,7 @@ struct text { struct property_layer property_layers[MAX_LAYERS]; uint32_t nproperty_layers; layer_id current_layer_id; + enum line_endings line_ends; }; struct text *text_create(uint32_t initial_capacity) { @@ -46,6 +47,7 @@ struct text *text_create(uint32_t initial_capacity) { txt->capacity = initial_capacity; txt->nlines = 0; txt->current_layer_id = 1; + txt->line_ends = LineEnding_LF; VEC_INIT(&txt->properties, 32); @@ -82,6 +84,10 @@ void text_clear(struct text *text) { text_clear_properties(text); } +enum line_endings text_get_line_ending(const struct text *text) { + return text->line_ends; +} + struct utf8_codepoint_iterator text_line_codepoint_iterator(const struct text *text, uint32_t lineidx) { if (lineidx >= text_num_lines(text)) { @@ -253,9 +259,16 @@ static void text_insert_at_inner(struct text *text, uint32_t line, uint8_t byte = bytes[bytei]; if (byte == '\n') { uint8_t *line_data = bytes + (bytei - linelen); - insert_at(text, line, offset, line_data, linelen); - offset += linelen; + uint32_t insertlen = linelen; + if (bytei > 0 && bytes[bytei - 1] == '\r') { + text->line_ends = LineEnding_CRLF; + --insertlen; + } + + insert_at(text, line, offset, line_data, insertlen); + + offset += insertlen; new_line_at(text, line, offset); ++line; diff --git a/src/dged/text.h b/src/dged/text.h index ec14650..108ded8 100644 --- a/src/dged/text.h +++ b/src/dged/text.h @@ -10,6 +10,11 @@ struct text; +enum line_endings { + LineEnding_LF, + LineEnding_CRLF, +}; + struct text_chunk { uint8_t *text; uint32_t nbytes; @@ -34,6 +39,8 @@ void text_append(struct text *text, uint8_t *bytes, uint32_t nbytes, void text_delete(struct text *text, uint32_t start_line, uint32_t start_offset, uint32_t end_line, uint32_t end_offset); +enum line_endings text_get_line_ending(const struct text *); + uint32_t text_num_lines(const struct text *text); uint32_t text_line_size(const struct text *text, uint32_t lineidx); struct utf8_codepoint_iterator |
