size_t len; /* length of the buffer */
} FMap;
-FMap fmap(char* path);
-void funmap(FMap file);
+FMap mmap_readonly(char* path);
+FMap mmap_readwrite(char* path, size_t sz);
+void mmap_close(FMap file);
uint64_t getmillis(void);
char* stringdup(const char* str);
char* fdgets(int fd);
void view_byrune(View* view, int move, bool extsel);
void view_byword(View* view, int move, bool extsel);
void view_byline(View* view, int move, bool extsel);
-void view_setcursor(View* view, size_t row, size_t col);
-void view_selext(View* view, size_t row, size_t col);
-void view_selword(View* view, size_t row, size_t col);
-void view_selprev(View* view);
-void view_select(View* view, size_t row, size_t col);
-size_t view_selsize(View* view);
+
char* view_fetch(View* view, size_t row, size_t col);
void view_find(View* view, size_t row, size_t col);
void view_findstr(View* view, char* str);
void view_setln(View* view, size_t line);
void view_indent(View* view, int dir);
+size_t view_selsize(View* view);
+void view_selprev(View* view);
+void view_setcursor(View* view, size_t row, size_t col);
+void view_selextend(View* view, size_t row, size_t col);
+void view_selword(View* view, size_t row, size_t col);
+void view_select(View* view, size_t row, size_t col);
+
/* Command Executions
*****************************************************************************/
void cmdreap(void);
#include <utf.h>
#include <edit.h>
#include <ctype.h>
+#include <unistd.h>
static void buf_resize(Buf* buf, size_t sz);
}
unsigned buf_load(Buf* buf, char* path) {
+ /* process the file path and address */
if (path && path[0] == '.' && path[1] == '/')
path += 2;
unsigned off = 0;
buf->path = stringdup(path);
char* addr = strrchr(buf->path, ':');
if (addr) *addr = '\0', addr++;
- if (!strcmp(buf->path,"-")) {
- buf->charset = UTF_8;
+
+ /* load the file and determine the character set */
+ FMap file = mmap_readonly(buf->path);
+ buf->charset = (file.buf ? charset(file.buf, file.len, &buf->crlf) : UTF_8);
+ if (buf->charset > UTF_8)
+ die("Unsupported character set");
+
+ /* read the file contents into the buffer */
+ for (size_t i = 0; i < file.len;) {
Rune r;
- while (RUNE_EOF != (r = fgetrune(stdin)))
- buf_insert(buf, false, buf_end(buf), r);
- } else {
- FMap file = fmap(buf->path);
- 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");
- } else if (buf->charset == BINARY) {
- binload(buf, file);
+ if (buf->charset == BINARY) {
+ r = file.buf[i++];
} else {
- utf8load(buf, file);
+ size_t len = 0;
+ while (!utf8decode(&r, &len, file.buf[i++]));
}
- funmap(file);
- if (addr)
- off = buf_setln(buf, strtoul(addr, NULL, 0));
+ buf_insert(buf, false, buf_end(buf), r);
}
+
+ /* reset buffer state */
buf->modified = false;
free(buf->undo);
buf->undo = NULL;
}
void buf_save(Buf* buf) {
+ size_t wrlen = 0;
if (!buf->path) return;
- FILE* file = fopen(buf->path, "wb");
- if (!file) return;
- if (buf->charset == BINARY)
- binsave(buf, file);
- else
- utf8save(buf, file);
- fclose(file);
+ FMap file = mmap_readwrite(buf->path, buf_end(buf) * UTF_MAX);
+ for (unsigned i = 0, end = buf_end(buf); i < end; i++) {
+ Rune r = buf_get(buf, i);
+ if (r == RUNE_CRLF) {
+ file.buf[wrlen++] = '\r';
+ file.buf[wrlen++] = '\n';
+ } else if (buf->charset == BINARY) {
+ file.buf[wrlen++] = (char)r;
+ } else {
+ wrlen += utf8encode((char*)&(file.buf[wrlen]), r);
+ }
+ }
+ mmap_close(file);
+ truncate(buf->path, wrlen);
buf->modified = false;
}
+++ /dev/null
-#include <carl.h>
-
-static Rune ranges[112][3] = {
- { 0x41, 0x5a, 32 },
- { 0xc0, 0xd6, 32 },
- { 0xd8, 0xde, 32 },
- { 0x130, 0x130, -199 },
- { 0x178, 0x178, -121 },
- { 0x181, 0x181, 210 },
- { 0x186, 0x186, 206 },
- { 0x189, 0x18a, 205 },
- { 0x18e, 0x18e, 79 },
- { 0x18f, 0x18f, 202 },
- { 0x190, 0x190, 203 },
- { 0x193, 0x193, 205 },
- { 0x194, 0x194, 207 },
- { 0x196, 0x196, 211 },
- { 0x197, 0x197, 209 },
- { 0x19c, 0x19c, 211 },
- { 0x19d, 0x19d, 213 },
- { 0x19f, 0x19f, 214 },
- { 0x1a6, 0x1a6, 218 },
- { 0x1a9, 0x1a9, 218 },
- { 0x1ae, 0x1ae, 218 },
- { 0x1b1, 0x1b2, 217 },
- { 0x1b7, 0x1b7, 219 },
- { 0x1c4, 0x1c4, 2 },
- { 0x1c7, 0x1c7, 2 },
- { 0x1ca, 0x1ca, 2 },
- { 0x1f1, 0x1f1, 2 },
- { 0x1f6, 0x1f6, -97 },
- { 0x1f7, 0x1f7, -56 },
- { 0x220, 0x220, -130 },
- { 0x23a, 0x23a, 10795 },
- { 0x23d, 0x23d, -163 },
- { 0x23e, 0x23e, 10792 },
- { 0x243, 0x243, -195 },
- { 0x244, 0x244, 69 },
- { 0x245, 0x245, 71 },
- { 0x37f, 0x37f, 116 },
- { 0x386, 0x386, 38 },
- { 0x388, 0x38a, 37 },
- { 0x38c, 0x38c, 64 },
- { 0x38e, 0x38f, 63 },
- { 0x391, 0x3a1, 32 },
- { 0x3a3, 0x3ab, 32 },
- { 0x3cf, 0x3cf, 8 },
- { 0x3f4, 0x3f4, -60 },
- { 0x3f9, 0x3f9, -7 },
- { 0x3fd, 0x3ff, -130 },
- { 0x400, 0x40f, 80 },
- { 0x410, 0x42f, 32 },
- { 0x4c0, 0x4c0, 15 },
- { 0x531, 0x556, 48 },
- { 0x10a0, 0x10c5, 7264 },
- { 0x10c7, 0x10c7, 7264 },
- { 0x10cd, 0x10cd, 7264 },
- { 0x13a0, 0x13ef, 38864 },
- { 0x13f0, 0x13f5, 8 },
- { 0x1e9e, 0x1e9e, -7615 },
- { 0x1f08, 0x1f0f, -8 },
- { 0x1f18, 0x1f1d, -8 },
- { 0x1f28, 0x1f2f, -8 },
- { 0x1f38, 0x1f3f, -8 },
- { 0x1f48, 0x1f4d, -8 },
- { 0x1f59, 0x1f59, -8 },
- { 0x1f5b, 0x1f5b, -8 },
- { 0x1f5d, 0x1f5d, -8 },
- { 0x1f5f, 0x1f5f, -8 },
- { 0x1f68, 0x1f6f, -8 },
- { 0x1f88, 0x1f8f, -8 },
- { 0x1f98, 0x1f9f, -8 },
- { 0x1fa8, 0x1faf, -8 },
- { 0x1fb8, 0x1fb9, -8 },
- { 0x1fba, 0x1fbb, -74 },
- { 0x1fbc, 0x1fbc, -9 },
- { 0x1fc8, 0x1fcb, -86 },
- { 0x1fcc, 0x1fcc, -9 },
- { 0x1fd8, 0x1fd9, -8 },
- { 0x1fda, 0x1fdb, -100 },
- { 0x1fe8, 0x1fe9, -8 },
- { 0x1fea, 0x1feb, -112 },
- { 0x1fec, 0x1fec, -7 },
- { 0x1ff8, 0x1ff9, -128 },
- { 0x1ffa, 0x1ffb, -126 },
- { 0x1ffc, 0x1ffc, -9 },
- { 0x2126, 0x2126, -7517 },
- { 0x212a, 0x212a, -8383 },
- { 0x212b, 0x212b, -8262 },
- { 0x2132, 0x2132, 28 },
- { 0x2160, 0x216f, 16 },
- { 0x24b6, 0x24cf, 26 },
- { 0x2c00, 0x2c2e, 48 },
- { 0x2c62, 0x2c62, -10743 },
- { 0x2c63, 0x2c63, -3814 },
- { 0x2c64, 0x2c64, -10727 },
- { 0x2c6d, 0x2c6d, -10780 },
- { 0x2c6e, 0x2c6e, -10749 },
- { 0x2c6f, 0x2c6f, -10783 },
- { 0x2c70, 0x2c70, -10782 },
- { 0x2c7e, 0x2c7f, -10815 },
- { 0xa77d, 0xa77d, -35332 },
- { 0xa78d, 0xa78d, -42280 },
- { 0xa7aa, 0xa7aa, -42308 },
- { 0xa7ab, 0xa7ab, -42319 },
- { 0xa7ac, 0xa7ac, -42315 },
- { 0xa7ad, 0xa7ad, -42305 },
- { 0xa7b0, 0xa7b0, -42258 },
- { 0xa7b1, 0xa7b1, -42282 },
- { 0xa7b2, 0xa7b2, -42261 },
- { 0xa7b3, 0xa7b3, 928 },
- { 0xff21, 0xff3a, 32 },
- { 0x10400, 0x10427, 40 },
- { 0x10c80, 0x10cb2, 64 },
- { 0x118a0, 0x118bf, 32 },
-};
-
-static Rune singles[531] = {
- 0x100,
- 0x102,
- 0x104,
- 0x106,
- 0x108,
- 0x10a,
- 0x10c,
- 0x10e,
- 0x110,
- 0x112,
- 0x114,
- 0x116,
- 0x118,
- 0x11a,
- 0x11c,
- 0x11e,
- 0x120,
- 0x122,
- 0x124,
- 0x126,
- 0x128,
- 0x12a,
- 0x12c,
- 0x12e,
- 0x132,
- 0x134,
- 0x136,
- 0x139,
- 0x13b,
- 0x13d,
- 0x13f,
- 0x141,
- 0x143,
- 0x145,
- 0x147,
- 0x14a,
- 0x14c,
- 0x14e,
- 0x150,
- 0x152,
- 0x154,
- 0x156,
- 0x158,
- 0x15a,
- 0x15c,
- 0x15e,
- 0x160,
- 0x162,
- 0x164,
- 0x166,
- 0x168,
- 0x16a,
- 0x16c,
- 0x16e,
- 0x170,
- 0x172,
- 0x174,
- 0x176,
- 0x179,
- 0x17b,
- 0x17d,
- 0x182,
- 0x184,
- 0x187,
- 0x18b,
- 0x191,
- 0x198,
- 0x1a0,
- 0x1a2,
- 0x1a4,
- 0x1a7,
- 0x1ac,
- 0x1af,
- 0x1b3,
- 0x1b5,
- 0x1b8,
- 0x1bc,
- 0x1c5,
- 0x1c8,
- 0x1cb,
- 0x1cd,
- 0x1cf,
- 0x1d1,
- 0x1d3,
- 0x1d5,
- 0x1d7,
- 0x1d9,
- 0x1db,
- 0x1de,
- 0x1e0,
- 0x1e2,
- 0x1e4,
- 0x1e6,
- 0x1e8,
- 0x1ea,
- 0x1ec,
- 0x1ee,
- 0x1f2,
- 0x1f4,
- 0x1f8,
- 0x1fa,
- 0x1fc,
- 0x1fe,
- 0x200,
- 0x202,
- 0x204,
- 0x206,
- 0x208,
- 0x20a,
- 0x20c,
- 0x20e,
- 0x210,
- 0x212,
- 0x214,
- 0x216,
- 0x218,
- 0x21a,
- 0x21c,
- 0x21e,
- 0x222,
- 0x224,
- 0x226,
- 0x228,
- 0x22a,
- 0x22c,
- 0x22e,
- 0x230,
- 0x232,
- 0x23b,
- 0x241,
- 0x246,
- 0x248,
- 0x24a,
- 0x24c,
- 0x24e,
- 0x370,
- 0x372,
- 0x376,
- 0x3d8,
- 0x3da,
- 0x3dc,
- 0x3de,
- 0x3e0,
- 0x3e2,
- 0x3e4,
- 0x3e6,
- 0x3e8,
- 0x3ea,
- 0x3ec,
- 0x3ee,
- 0x3f7,
- 0x3fa,
- 0x460,
- 0x462,
- 0x464,
- 0x466,
- 0x468,
- 0x46a,
- 0x46c,
- 0x46e,
- 0x470,
- 0x472,
- 0x474,
- 0x476,
- 0x478,
- 0x47a,
- 0x47c,
- 0x47e,
- 0x480,
- 0x48a,
- 0x48c,
- 0x48e,
- 0x490,
- 0x492,
- 0x494,
- 0x496,
- 0x498,
- 0x49a,
- 0x49c,
- 0x49e,
- 0x4a0,
- 0x4a2,
- 0x4a4,
- 0x4a6,
- 0x4a8,
- 0x4aa,
- 0x4ac,
- 0x4ae,
- 0x4b0,
- 0x4b2,
- 0x4b4,
- 0x4b6,
- 0x4b8,
- 0x4ba,
- 0x4bc,
- 0x4be,
- 0x4c1,
- 0x4c3,
- 0x4c5,
- 0x4c7,
- 0x4c9,
- 0x4cb,
- 0x4cd,
- 0x4d0,
- 0x4d2,
- 0x4d4,
- 0x4d6,
- 0x4d8,
- 0x4da,
- 0x4dc,
- 0x4de,
- 0x4e0,
- 0x4e2,
- 0x4e4,
- 0x4e6,
- 0x4e8,
- 0x4ea,
- 0x4ec,
- 0x4ee,
- 0x4f0,
- 0x4f2,
- 0x4f4,
- 0x4f6,
- 0x4f8,
- 0x4fa,
- 0x4fc,
- 0x4fe,
- 0x500,
- 0x502,
- 0x504,
- 0x506,
- 0x508,
- 0x50a,
- 0x50c,
- 0x50e,
- 0x510,
- 0x512,
- 0x514,
- 0x516,
- 0x518,
- 0x51a,
- 0x51c,
- 0x51e,
- 0x520,
- 0x522,
- 0x524,
- 0x526,
- 0x528,
- 0x52a,
- 0x52c,
- 0x52e,
- 0x1e00,
- 0x1e02,
- 0x1e04,
- 0x1e06,
- 0x1e08,
- 0x1e0a,
- 0x1e0c,
- 0x1e0e,
- 0x1e10,
- 0x1e12,
- 0x1e14,
- 0x1e16,
- 0x1e18,
- 0x1e1a,
- 0x1e1c,
- 0x1e1e,
- 0x1e20,
- 0x1e22,
- 0x1e24,
- 0x1e26,
- 0x1e28,
- 0x1e2a,
- 0x1e2c,
- 0x1e2e,
- 0x1e30,
- 0x1e32,
- 0x1e34,
- 0x1e36,
- 0x1e38,
- 0x1e3a,
- 0x1e3c,
- 0x1e3e,
- 0x1e40,
- 0x1e42,
- 0x1e44,
- 0x1e46,
- 0x1e48,
- 0x1e4a,
- 0x1e4c,
- 0x1e4e,
- 0x1e50,
- 0x1e52,
- 0x1e54,
- 0x1e56,
- 0x1e58,
- 0x1e5a,
- 0x1e5c,
- 0x1e5e,
- 0x1e60,
- 0x1e62,
- 0x1e64,
- 0x1e66,
- 0x1e68,
- 0x1e6a,
- 0x1e6c,
- 0x1e6e,
- 0x1e70,
- 0x1e72,
- 0x1e74,
- 0x1e76,
- 0x1e78,
- 0x1e7a,
- 0x1e7c,
- 0x1e7e,
- 0x1e80,
- 0x1e82,
- 0x1e84,
- 0x1e86,
- 0x1e88,
- 0x1e8a,
- 0x1e8c,
- 0x1e8e,
- 0x1e90,
- 0x1e92,
- 0x1e94,
- 0x1ea0,
- 0x1ea2,
- 0x1ea4,
- 0x1ea6,
- 0x1ea8,
- 0x1eaa,
- 0x1eac,
- 0x1eae,
- 0x1eb0,
- 0x1eb2,
- 0x1eb4,
- 0x1eb6,
- 0x1eb8,
- 0x1eba,
- 0x1ebc,
- 0x1ebe,
- 0x1ec0,
- 0x1ec2,
- 0x1ec4,
- 0x1ec6,
- 0x1ec8,
- 0x1eca,
- 0x1ecc,
- 0x1ece,
- 0x1ed0,
- 0x1ed2,
- 0x1ed4,
- 0x1ed6,
- 0x1ed8,
- 0x1eda,
- 0x1edc,
- 0x1ede,
- 0x1ee0,
- 0x1ee2,
- 0x1ee4,
- 0x1ee6,
- 0x1ee8,
- 0x1eea,
- 0x1eec,
- 0x1eee,
- 0x1ef0,
- 0x1ef2,
- 0x1ef4,
- 0x1ef6,
- 0x1ef8,
- 0x1efa,
- 0x1efc,
- 0x1efe,
- 0x2183,
- 0x2c60,
- 0x2c67,
- 0x2c69,
- 0x2c6b,
- 0x2c72,
- 0x2c75,
- 0x2c80,
- 0x2c82,
- 0x2c84,
- 0x2c86,
- 0x2c88,
- 0x2c8a,
- 0x2c8c,
- 0x2c8e,
- 0x2c90,
- 0x2c92,
- 0x2c94,
- 0x2c96,
- 0x2c98,
- 0x2c9a,
- 0x2c9c,
- 0x2c9e,
- 0x2ca0,
- 0x2ca2,
- 0x2ca4,
- 0x2ca6,
- 0x2ca8,
- 0x2caa,
- 0x2cac,
- 0x2cae,
- 0x2cb0,
- 0x2cb2,
- 0x2cb4,
- 0x2cb6,
- 0x2cb8,
- 0x2cba,
- 0x2cbc,
- 0x2cbe,
- 0x2cc0,
- 0x2cc2,
- 0x2cc4,
- 0x2cc6,
- 0x2cc8,
- 0x2cca,
- 0x2ccc,
- 0x2cce,
- 0x2cd0,
- 0x2cd2,
- 0x2cd4,
- 0x2cd6,
- 0x2cd8,
- 0x2cda,
- 0x2cdc,
- 0x2cde,
- 0x2ce0,
- 0x2ce2,
- 0x2ceb,
- 0x2ced,
- 0x2cf2,
- 0xa640,
- 0xa642,
- 0xa644,
- 0xa646,
- 0xa648,
- 0xa64a,
- 0xa64c,
- 0xa64e,
- 0xa650,
- 0xa652,
- 0xa654,
- 0xa656,
- 0xa658,
- 0xa65a,
- 0xa65c,
- 0xa65e,
- 0xa660,
- 0xa662,
- 0xa664,
- 0xa666,
- 0xa668,
- 0xa66a,
- 0xa66c,
- 0xa680,
- 0xa682,
- 0xa684,
- 0xa686,
- 0xa688,
- 0xa68a,
- 0xa68c,
- 0xa68e,
- 0xa690,
- 0xa692,
- 0xa694,
- 0xa696,
- 0xa698,
- 0xa69a,
- 0xa722,
- 0xa724,
- 0xa726,
- 0xa728,
- 0xa72a,
- 0xa72c,
- 0xa72e,
- 0xa732,
- 0xa734,
- 0xa736,
- 0xa738,
- 0xa73a,
- 0xa73c,
- 0xa73e,
- 0xa740,
- 0xa742,
- 0xa744,
- 0xa746,
- 0xa748,
- 0xa74a,
- 0xa74c,
- 0xa74e,
- 0xa750,
- 0xa752,
- 0xa754,
- 0xa756,
- 0xa758,
- 0xa75a,
- 0xa75c,
- 0xa75e,
- 0xa760,
- 0xa762,
- 0xa764,
- 0xa766,
- 0xa768,
- 0xa76a,
- 0xa76c,
- 0xa76e,
- 0xa779,
- 0xa77b,
- 0xa77e,
- 0xa780,
- 0xa782,
- 0xa784,
- 0xa786,
- 0xa78b,
- 0xa790,
- 0xa792,
- 0xa796,
- 0xa798,
- 0xa79a,
- 0xa79c,
- 0xa79e,
- 0xa7a0,
- 0xa7a2,
- 0xa7a4,
- 0xa7a6,
- 0xa7a8,
- 0xa7b4,
- 0xa7b6,
-};
-
-static int runecmp(const void* a, const void* b) {
- Rune* ra = (Rune*)a;
- Rune* rb = (Rune*)b;
- return *ra - *rb;
-}
-
-static int runerangecmp(const void* a, const void* b) {
- Rune* ra = (Rune*)a;
- Rune* rb = (Rune*)b;
- if (rb[0] > *ra)
- return -1;
- else if (rb[1] < *ra)
- return 1;
- else
- return 0;
-}
-
-Rune tolowerrune(Rune ch) {
- Rune* to = bsearch(&ch, ranges, 112, 3 * sizeof(Rune), &runerangecmp);
- if (to) return (ch + to[2]);
- to = bsearch(&ch, singles, 531, sizeof(Rune), &runecmp);
- return (to ? (ch + 1) : ch);
-}
#include <time.h>
#include <sys/time.h>
+static size_t pagealign(size_t sz) {
+ size_t pgsize = sysconf(_SC_PAGE_SIZE);
+ size_t alignmask = pgsize - 1;
+ if (sz & alignmask)
+ sz += pgsize - (sz & alignmask);
+ return sz;
+}
+
uint64_t getmillis(void) {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
exit(EXIT_FAILURE);
}
-FMap fmap(char* path) {
- int fd;
+FMap mmap_readonly(char* path) {
FMap file = { .buf = NULL, .len = 0 };
+ int fd;
struct stat sb;
if (((fd = open(path, O_RDONLY, 0)) < 0) ||
(fstat(fd, &sb) < 0) ||
(sb.st_size == 0))
return file;
- file.buf = (uint8_t*)mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ file.buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
file.len = sb.st_size;
if (file.buf == MAP_FAILED)
die("memory mapping of file failed");
+ close(fd);
+ return file;
+}
+
+FMap mmap_readwrite(char* path, size_t sz) {
+ FMap file = { .buf = NULL, .len = 0 };
+ int fd = open(path, O_CREAT|O_RDWR, 0644);
+ if (fd < 0) die("could not open/create file");
+ ftruncate(fd, sz);
+ file.buf = mmap(NULL, pagealign(sz), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ file.len = sz;
+ if (file.buf == MAP_FAILED)
+ die("memory mapping of file failed");
+ close(fd);
return file;
}
-void funmap(FMap file) {
+void mmap_close(FMap file) {
if (file.buf)
munmap(file.buf, file.len);
}