aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--text.c20
-rw-r--r--text.h11
-rw-r--r--vis.c13
3 files changed, 33 insertions, 11 deletions
diff --git a/text.c b/text.c
index 553a3cb..eca86db 100644
--- a/text.c
+++ b/text.c
@@ -118,7 +118,7 @@ struct Text {
struct stat info; /* stat as proped on load time */
int fd; /* the file descriptor of the original mmap-ed data */
LineCache lines; /* mapping between absolute pos in bytes and logical line breaks */
- int newlines; /* 0: unknown, 1: \n, -1: \r\n */
+ enum TextNewLine newlines; /* which type of new lines does the file use */
};
/* buffer management */
@@ -902,18 +902,23 @@ bool text_modified(Text *txt) {
return txt->saved_action != txt->undo;
}
-bool text_newlines_crnl(Text *txt){
- if (txt->newlines == 0) {
- txt->newlines = 1; /* default to UNIX style \n new lines */
+enum TextNewLine text_newline_type(Text *txt){
+ if (!txt->newlines) {
+ txt->newlines = TEXT_NEWLINE_NL; /* default to UNIX style \n new lines */
const char *start = txt->buf.data;
if (start) {
const char *nl = memchr(start, '\n', txt->buf.len);
if (nl > start && nl[-1] == '\r')
- txt->newlines = -1; /* Windows style \r\n */
+ txt->newlines = TEXT_NEWLINE_CRNL;
+ } else {
+ char c;
+ size_t nl = lines_skip_forward(txt, 0, 1, NULL);
+ if (nl > 1 && text_byte_get(txt, nl-2, &c) && c == '\r')
+ txt->newlines = TEXT_NEWLINE_CRNL;
}
}
- return txt->newlines < 0;
+ return txt->newlines;
}
static bool text_iterator_init(Iterator *it, size_t pos, Piece *p, size_t off) {
@@ -1088,7 +1093,8 @@ static size_t lines_skip_forward(Text *txt, size_t pos, size_t lines, size_t *li
if (lines == 0)
break;
}
- *lines_skipped = lines_old - lines;
+ if (lines_skipped)
+ *lines_skipped = lines_old - lines;
return pos;
}
diff --git a/text.h b/text.h
index 9f350f9..099cbe4 100644
--- a/text.h
+++ b/text.h
@@ -82,8 +82,15 @@ size_t text_history_get(Text*, size_t index);
size_t text_size(Text*);
bool text_modified(Text*);
-/* test whether the underlying file uses UNIX style \n or Windows style \r\n newlines */
-bool text_newlines_crnl(Text*);
+
+/* which type of new lines does the text use? */
+enum TextNewLine {
+ TEXT_NEWLINE_NL = 1,
+ TEXT_NEWLINE_CRNL,
+};
+
+enum TextNewLine text_newline_type(Text*);
+
bool text_save(Text*, const char *file);
bool text_range_save(Text*, Filerange*, const char *file);
ssize_t text_write(Text*, int fd);
diff --git a/vis.c b/vis.c
index 8466034..e1ed0de 100644
--- a/vis.c
+++ b/vis.c
@@ -1092,8 +1092,17 @@ static void copy_indent_from_previous_line(View *view, Text *text) {
}
static void insert_newline(const Arg *arg) {
- insert(&(const Arg){ .s =
- text_newlines_crnl(vis->win->file->text) ? "\r\n" : "\n" });
+ const char *nl;
+ switch (text_newline_type(vis->win->file->text)) {
+ case TEXT_NEWLINE_CRNL:
+ nl = "\r\n";
+ break;
+ default:
+ nl = "\n";
+ break;
+ }
+
+ insert(&(const Arg){ .s = nl });
if (vis->autoindent)
copy_indent_from_previous_line(vis->win->view, vis->win->file->text);