} else {
FMap file = fmap(path);
buf->path = strdup(path);
- buf->charset = (file.buf ? charset(file.buf, file.len) : UTF_8);
+ buf->charset = (file.buf ? charset(file.buf, file.len, &buf->crlf) : UTF_8);
/* load the file contents if it has any */
if (buf->charset > UTF_8) {
die("Unsupported character set");
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
};
-int charset(const uint8_t* buf, size_t len) {
+int charset(const uint8_t* buf, size_t len, int* crlf) {
+ size_t crs = 0;
+ size_t lfs = 0;
/* look for a BOM and parse it */
for (size_t i = 0; i < (sizeof(BOMS)/sizeof(BOMS[0])); i++)
if (!strncmp((char*)buf, BOMS[i].seq, BOMS[i].len))
/* look for bytes that are invalid in utf-8 */
int type = UTF_8;
size_t i = 0;
- for (i = 0; type && (i < len); i++)
- type = Utf8Valid[(int)buf[i]];
+ for (i = 0; i < len; i++) {
+ type &= Utf8Valid[(int)buf[i]];
+ switch(buf[i]) {
+ case '\r': crs++; break;
+ case '\n': lfs++; break;
+ }
+ }
+ /* report back the linefeed mode */
+ *crlf = (crs > (lfs / 2));
return type;
}
typedef struct buf {
char* path; /* the path to the open file */
int charset; /* the character set of the buffer */
+ int crlf; /* tracks whether the file uses dos style line endings */
bool insert_mode; /* tracks current mode */
bool modified; /* tracks whether the buffer has been modified */
size_t bufsize; /* size of the buffer in runes */
UTF_32LE, /* UTF-32 encoding, little-endian */
};
-int charset(const uint8_t* buf, size_t len);
+int charset(const uint8_t* buf, size_t len, int* crlf);
void utf8load(Buf* buf, FMap file);
void utf8save(Buf* buf, FILE* file);
void binload(Buf* buf, FMap file);
#ifdef __MACH__
#define FONTNAME "Monaco:size=10:antialias=true:autohint=true"
#else
-#define FONTNAME "Monaco:size=10.5:antialias=true:autohint=true"
+#define FONTNAME "Liberation Mono:size=10.5:antialias=true:autohint=true"
#endif
#define DEFAULT_COLORSCHEME DARK
TargetCol = buf_getcol(&Buffer, CursorPos);
}
+static void insert(Rune r) {
+ if (r == '\n' && Buffer.crlf)
+ buf_ins(&Buffer, CursorPos++, '\r');
+ buf_ins(&Buffer, CursorPos++, r);
+}
+
void handle_key(Rune key) {
/* ignore invalid keys */
if (key == RUNE_ERR) return;
static void control_keys(Rune key) {
switch (key) {
- case KEY_ESCAPE: Buffer.insert_mode = false; break;
- case KEY_BACKSPACE: backspace(); break;
- case KEY_CTRL_W: buf_save(&Buffer); break;
- case KEY_CTRL_Q: exit(0); break;
- default: buf_ins(&Buffer, CursorPos++, key); break;
+ case KEY_ESCAPE: Buffer.insert_mode = false; break;
+ case KEY_BACKSPACE: backspace(); break;
+ case KEY_CTRL_W: buf_save(&Buffer); break;
+ case KEY_CTRL_Q: exit(0); break;
+ default: insert(key); break;
}
}