summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dged/buffer.c21
-rw-r--r--src/dged/text.c17
-rw-r--r--src/dged/text.h7
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