]> git.mdlowis.com Git - projs/tide.git/commitdiff
general cleanup of warnings and switch over to C99 instead og GNU99. Also first,...
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 5 Nov 2016 00:20:00 +0000 (20:20 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 5 Nov 2016 00:20:00 +0000 (20:20 -0400)
Makefile
inc/X.h
inc/edit.h
inc/vec.h [new file with mode: 0644]
libedit/buf.c
libedit/charset.c
libedit/tolower.c [new file with mode: 0644]
libedit/utf8.c
libedit/utils.c
libx/x11.c
xpick.c

index 7a305fdfcf997b19c1584912c1723ba3cd88b10d..71c69dbe26e8eef9d265606c60194dc7ddcef5ea 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,11 @@
 CC = c99
 LDFLAGS = -L/usr/X11/lib -lX11 -lXft -lfontconfig
-CFLAGS = -Os -Iinc/ -I/usr/X11/include -I/usr/X11/include/freetype2
+CFLAGS = -Os $(INCS)
+INCS =                           \
+       -Iinc/                       \
+       -I/usr/X11/include           \
+       -I/usr/X11/include/freetype2 \
+       -I/usr/include/freetype2
 
 LIBEDIT_OBJS =         \
        libedit/buf.o      \
diff --git a/inc/X.h b/inc/X.h
index 0301c948f295dde15818d3b8d57c4aecd7c5100e..02c64af2de4ef2c2cd616b95b2eb521c9ab0fa8d 100644 (file)
--- a/inc/X.h
+++ b/inc/X.h
@@ -1,5 +1,4 @@
 #include <X11/Xft/Xft.h>
-#include <stdint.h>
 
 typedef enum {
     MOUSE_ACT_UP,
@@ -134,3 +133,4 @@ void x11_warp_mouse(int x, int y);
 void x11_font_load(XFont* font, char* name);
 void x11_font_getglyph(XFont* font, XftGlyphFontSpec* spec, uint32_t rune);
 size_t x11_font_getglyphs(XftGlyphFontSpec* specs, const XGlyph* glyphs, int len, XFont* font, int x, int y);
+void x11_draw_utf8(XFont* font, int fg, int bg, int x, int y, char* str);
index ef1645d9b2920a83479870fc41f2eebc33ac400e..80d4693d3fa0e8b75ab70cf7777f512354519d62 100644 (file)
@@ -10,6 +10,7 @@ void funmap(FMap file);
 uint32_t getmillis(void);
 bool risword(Rune r);
 bool risblank(Rune r);
+char* stringdup(const char* str);
 
 /* Buffer management functions
  *****************************************************************************/
diff --git a/inc/vec.h b/inc/vec.h
new file mode 100644 (file)
index 0000000..c7b6113
--- /dev/null
+++ b/inc/vec.h
@@ -0,0 +1,120 @@
+/**
+  @brief Generic vector implementation.
+  @author Michael D. Lowis
+  @license BSD 2-clause License
+*/
+#ifndef VEC_H
+#define VEC_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+    size_t   elem_count;
+    size_t   elem_size;
+    size_t   elem_capacity;
+    uint8_t* elem_buffer;
+} vec_t;
+
+typedef int (*vec_cmpfn_t)(const void*,const void*);
+
+#ifndef DEFAULT_VEC_CAPACITY
+#define DEFAULT_VEC_CAPACITY (size_t)8
+#endif
+
+static void vec_init(vec_t* vec, size_t elem_size) {
+    vec->elem_size     = elem_size;
+    vec->elem_count    = 0;
+    vec->elem_capacity = DEFAULT_VEC_CAPACITY;
+    vec->elem_buffer   = malloc(elem_size * vec->elem_capacity);
+}
+
+static size_t vec_size(vec_t* vec) {
+    return vec->elem_count;
+}
+
+static bool vec_empty(vec_t* vec) {
+    return (vec->elem_count == 0);
+}
+
+static size_t vec_capacity(vec_t* vec) {
+    return vec->elem_capacity;
+}
+
+static size_t vec_next_capacity(size_t req_size) {
+    size_t next_power = req_size;
+    size_t num_bits = sizeof(size_t) * 8;
+    size_t bit_n;
+
+    /* Find the next highest power of 2 */
+    next_power--;
+    for (bit_n = 1; bit_n < num_bits; bit_n = bit_n << 1)
+        next_power = next_power | (next_power >> bit_n);
+    next_power++;
+
+    return next_power;
+}
+
+static void vec_reserve(vec_t* vec, size_t size) {
+    vec->elem_buffer   = realloc(vec->elem_buffer, size * vec->elem_size);
+    vec->elem_capacity = size;
+}
+
+static void vec_resize(vec_t* vec, size_t count, void* fillval) {
+    if (count > vec->elem_count) {
+        vec_reserve(vec, vec_next_capacity(count+1));
+        for (; vec->elem_count < count; vec->elem_count++)
+            memcpy(&(vec->elem_buffer[vec->elem_count * vec->elem_size]), fillval, vec->elem_size);
+    } else if (count < vec->elem_count) {
+        vec->elem_count = count;
+    }
+}
+
+static void vec_shrink_to_fit(vec_t* vec) {
+    vec->elem_buffer   = realloc(vec->elem_buffer, vec->elem_count * vec->elem_size);
+    vec->elem_capacity = vec->elem_count;
+}
+
+static void* vec_at(vec_t* vec, size_t index) {
+    return &(vec->elem_buffer[index * vec->elem_size]);
+}
+
+static void vec_set(vec_t* vec, size_t index, void* data) {
+    memcpy(&(vec->elem_buffer[index * vec->elem_size]), data, vec->elem_size);
+}
+
+static bool vec_insert(vec_t* vec, size_t index, size_t num_elements, ...) {
+    (void)vec;
+    (void)index;
+    (void)num_elements;
+    return false;
+}
+
+static bool vec_erase(vec_t* vec, size_t start_idx, size_t end_idx) {
+    (void)vec;
+    (void)start_idx;
+    (void)end_idx;
+    return false;
+}
+
+static void vec_push_back(vec_t* vec, void* data) {
+    vec_resize(vec, vec->elem_count+1, data);
+}
+
+static void vec_pop_back(vec_t* vec, void* outdata) {
+    vec->elem_count--;
+    memcpy(outdata, &(vec->elem_buffer[vec->elem_count * vec->elem_size]), vec->elem_size);
+}
+
+static void vec_clear(vec_t* vec) {
+    vec->elem_count = 0;
+}
+
+static void vec_sort(vec_t* vec, int (*cmpfn)(const void*,const void*)) {
+    qsort(vec->elem_buffer, vec->elem_count, vec->elem_size, cmpfn);
+}
+
+#endif /* VEC_H */
index 63f257de841e7c84081a7ef39f6c513ef4b8e4f6..591a183cff47036271fe3fc4dc0b8ddb97ca4a0f 100644 (file)
@@ -8,10 +8,10 @@ void buf_load(Buf* buf, char* path) {
         buf->charset = UTF_8;
         Rune r;
         while (RUNE_EOF != (r = fgetrune(stdin)))
-            buf_ins(buf, buf_end(&Buffer), r);
+            buf_ins(buf, buf_end(buf), r);
     } else {
         FMap file = fmap(path);
-        buf->path = strdup(path);
+        buf->path = stringdup(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) {
@@ -22,8 +22,8 @@ void buf_load(Buf* buf, char* path) {
             utf8load(buf, file);
         }
         /* new files should have a newline in the buffer */
-        if (!file.buf)
-            buf_ins(buf, 0, (Rune)'\n');
+        //if (!file.buf)
+        //    buf_ins(buf, 0, (Rune)'\n');
         funmap(file);
     }
     buf_setlocked(buf, true);
index 6051db1f622501e6337f00dff3914b9691e6cf7f..336e317ba4904b25dce898344ace5be06ce5fa51 100644 (file)
@@ -5,13 +5,13 @@
 static const struct {
     int type;
     int len;
-    char* seq;
+    uchar* seq;
 } BOMS[] = {
-    { .type = UTF_8,    .len = 3, .seq = (char[]){ 0xEF, 0xBB, 0xBF       }},
-    { .type = UTF_16BE, .len = 2, .seq = (char[]){ 0xFE, 0xFF             }},
-    { .type = UTF_16LE, .len = 2, .seq = (char[]){ 0xFF, 0xFE             }},
-    { .type = UTF_32BE, .len = 4, .seq = (char[]){ 0x00, 0x00, 0xFE, 0xFF }},
-    { .type = UTF_32LE, .len = 4, .seq = (char[]){ 0xFF, 0xFE, 0x00, 0x00 }},
+    { .type = UTF_8,    .len = 3, .seq = (uchar[]){ 0xEFu, 0xBBu, 0xBFu        }},
+    { .type = UTF_16BE, .len = 2, .seq = (uchar[]){ 0xFEu, 0xFFu               }},
+    { .type = UTF_16LE, .len = 2, .seq = (uchar[]){ 0xFFu, 0xFEu               }},
+    { .type = UTF_32BE, .len = 4, .seq = (uchar[]){ 0x00u, 0x00u, 0xFEu, 0xFFu }},
+    { .type = UTF_32LE, .len = 4, .seq = (uchar[]){ 0xFFu, 0xFEu, 0x00u, 0x00u }},
 };
 
 static const char Utf8Valid[256] = {
@@ -30,7 +30,7 @@ int charset(const uint8_t* buf, size_t len, int* crlf) {
     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))
+        if (!strncmp((char*)buf, (char*)BOMS[i].seq, BOMS[i].len))
             return BOMS[i].type;
     /* look for bytes that are invalid in utf-8 */
     int type = UTF_8;
diff --git a/libedit/tolower.c b/libedit/tolower.c
new file mode 100644 (file)
index 0000000..bbe0311
--- /dev/null
@@ -0,0 +1,674 @@
+#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);
+}
index c96a7a6381604bc5f32bae6f9f0dc6f42fc2f1a6..78325dc21205449fe65c6857c6a70002176836b7 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdc.h>
 #include <utf.h>
 #include <edit.h>
+#define __USE_XOPEN
 #include <wchar.h>
 
 const uint8_t UTF8_SeqBits[] = { 0x00u, 0x80u, 0xC0u, 0xE0u, 0xF0u, 0xF8u, 0xFCu, 0xFEu };
index 7003c338b4140a5da0eae3fec74149817aa379d3..4a6d231883f65bb0ec651efb37fc9c1d0067a270 100644 (file)
@@ -1,13 +1,13 @@
 #include <stdc.h>
 #include <utf.h>
 #include <edit.h>
-#include <time.h>
-#include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <ctype.h>
+#include <time.h>
+#include <sys/time.h>
 
 #ifdef __MACH__
 #define CLOCK_MONOTONIC 0
@@ -66,3 +66,9 @@ bool risword(Rune r) {
 bool risblank(Rune r) {
     return (r == ' ' || r == '\t' || r == '\n' || r == '\r' || r == RUNE_CRLF);
 }
+
+char* stringdup(const char* s) {
+    char* ns = (char*)malloc(strlen(s) + 1);
+    strcpy(ns,s);
+    return ns;
+}
index 9a511601eccfdc77c7119d441c1d42d499afbaaf..60e7c220671c863f455b3176ade6a231f7ca33bb 100644 (file)
@@ -5,6 +5,7 @@
 #include <utf.h>
 #include <locale.h>
 
+static bool Running = true;
 static struct {
     Window root;
     Display* display;
@@ -33,7 +34,7 @@ static void xftcolor(XftColor* xc, uint32_t c) {
 }
 
 void x11_deinit(void) {
-    XCloseDisplay(X.display);
+    Running = false;
 }
 
 void x11_init(XConfig* cfg) {
@@ -184,7 +185,7 @@ static void handle_mouse(XEvent* e) {
 
 void x11_loop(void) {
     XEvent e;
-    while (true) {
+    while (Running) {
         XPeekEvent(X.display,&e);
         while (XPending(X.display)) {
             XNextEvent(X.display, &e);
@@ -210,6 +211,7 @@ void x11_loop(void) {
         XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0);
         XFlush(X.display);
     }
+    XCloseDisplay(X.display);
 }
 
 void x11_draw_rect(int color, int x, int y, int width, int height) {
@@ -334,6 +336,20 @@ size_t x11_font_getglyphs(XftGlyphFontSpec* specs, const XGlyph* glyphs, int len
     return numspecs;
 }
 
+void x11_draw_utf8(XFont* font, int fg, int bg, int x, int y, char* str) {
+    static XftGlyphFontSpec specs[256];
+    size_t nspecs = 0;
+    while (*str && nspecs < 256) {
+        x11_font_getglyph(font, &(specs[nspecs]), *str);
+        specs[nspecs].x = x;
+        specs[nspecs].y = y;
+        x += font->base.width;
+        nspecs++;
+        str++;
+    }
+    x11_draw_glyphs(fg, bg, specs, nspecs);
+}
+
 void x11_warp_mouse(int x, int y) {
     XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y);
 }
diff --git a/xpick.c b/xpick.c
index 9f3ef7dc6f75d4e0f7d27f8ed289490aa0bca4c3..257c28be7f9859c15666bf0deb8fc47d2b4ef3c4 100644 (file)
--- a/xpick.c
+++ b/xpick.c
@@ -2,18 +2,31 @@
 #include <X.h>
 #include <utf.h>
 #include <edit.h>
+#include <vec.h>
+#include <ctype.h>
 
 static void redraw(int width, int height);
 static void mouse_input(MouseAct act, MouseBtn btn, int x, int y);
 static void keyboard_input(uint32_t key);
 
-Buf Buffer;
+typedef struct {
+    float score;
+    char* string;
+    size_t length;
+    size_t match_start;
+    size_t match_end;
+} Choice;
+
+static unsigned Pos = 0;
+static Buf Query;
+static vec_t Choices = {0};
+static size_t ChoiceIdx = 0;
 static XFont Fonts;
 static XConfig Config = {
     .redraw       = redraw,
     .handle_key   = keyboard_input,
     .handle_mouse = mouse_input,
-    .palette    = {
+    .palette      = {
         /* ARGB color values */
         0xff002b36,
         0xff073642,
@@ -34,11 +47,128 @@ static XConfig Config = {
     }
 };
 
+static char* rdline(FILE* fin) {
+    if (feof(fin) || ferror(fin))
+        return NULL;
+    size_t size  = 256;
+    size_t index = 0;
+    char*  str   = (char*)malloc(size);
+    while (true) {
+        char ch = fgetc(fin);
+        if (ch == EOF) break;
+        str[index++] = ch;
+        str[index]   = '\0';
+        if (index+1 >= size) {
+            size = size << 1;
+            str  = realloc(str, size);
+        }
+        if (ch == '\n') break;
+    }
+    return str;
+}
+
+static int by_score(const void* a, const void* b) {
+    Choice* ca = ((Choice*)a);
+    Choice* cb = ((Choice*)b);
+    if (ca->score < cb->score)
+        return 1;
+    else if (ca->score > cb->score)
+        return -1;
+    else
+        return strcmp(ca->string, cb->string);
+}
+
+static void load_choices(void) {
+    char* choice_text;
+    Choice choice = {0};
+    vec_init(&Choices, sizeof(Choice));
+    while ((choice_text = rdline(stdin)) != NULL) {
+        choice_text[strlen(choice_text)-1] = '\0';
+        if (strlen(choice_text) > 0) {
+            choice.string = choice_text;
+            choice.length = strlen(choice_text);
+            choice.score  = 1.0;
+            vec_push_back(&Choices, &choice);
+        }
+    }
+    vec_sort(&Choices, by_score);
+}
+
+static char* find_match_start(char *str, int ch) {
+    for (; *str; str++)
+        if (tolower(*str) == tolower(ch))
+            return str;
+    return NULL;
+}
+
+static bool match(char *string, size_t offset, size_t *start, size_t *end) {
+    unsigned qpos = 0;
+    char* s = find_match_start(&string[offset], buf_get(&Query, qpos));
+    char* e = s;
+    /* bail if no match for first char */
+    if (s == NULL) return 0;
+    /* find the end of the match */
+    for (unsigned bend = buf_end(&Query); qpos < bend; qpos++)
+        if ((e = find_match_start(e, buf_get(&Query, qpos))) == NULL)
+            return false;
+    /* make note of the matching range */
+    *start = s - string;
+    *end   = e - string;
+    /* Less than or equal is used in order to obtain the left-most match. */
+    if (match(string, offset + 1, start, end) && (size_t)(e - s) <= *end - *start) {
+        *start = s - string;
+        *end   = e - string;
+    }
+    return true;
+}
+
+static void score(void) {
+    for (int i = 0; i < vec_size(&Choices); i++) {
+        Choice* choice = (Choice*)vec_at(&Choices, i);
+        float qlen = (float)buf_end(&Query);
+        if (match(choice->string, 0, &choice->match_start, &choice->match_end)) {
+            float clen = (float)(choice->match_end - choice->match_start);
+            choice->score = qlen / clen / (float)(choice->length);
+        } else {
+            choice->match_start = 0;
+            choice->match_end   = 0;
+            choice->score       = 0.0f;
+        }
+    }
+    vec_sort(&Choices, by_score);
+}
+
+static void draw_runes(unsigned x, unsigned y, int fg, int bg, XGlyph* glyphs, size_t rlen) {
+    XftGlyphFontSpec specs[rlen];
+    while (rlen) {
+        size_t nspecs = x11_font_getglyphs(specs, glyphs, rlen, &Fonts, x, y);
+        x11_draw_glyphs(fg, bg, specs, nspecs);
+        rlen -= nspecs;
+    }
+}
+
 static void redraw(int width, int height) {
     /* draw the background colors */
     x11_draw_rect(CLR_BASE03, 0, 0, width, height);
     x11_draw_rect(CLR_BASE02, 0, 0, width, Fonts.base.height);
     x11_draw_rect(CLR_BASE01, 0, Fonts.base.height, width, 1);
+    /* create the array for the query glyphs */
+    height = height / Fonts.base.height - 1,
+    width  = width  / Fonts.base.width;
+    XGlyph glyphs[width], *text = glyphs;
+    /* draw the query */
+    unsigned start = 0, end = buf_end(&Query);
+    while (start < end)
+        (text++)->rune = buf_get(&Query, start++);
+    draw_runes(0, 0, CLR_BASE3, CLR_BASE03, glyphs, text - glyphs);
+
+    for (size_t i = 0; i < vec_size(&Choices) && i < height; i++) {
+        Choice* choice = vec_at(&Choices, i);
+        if (i == ChoiceIdx)
+            x11_draw_utf8(&Fonts, CLR_BASE03, CLR_BASE1, 0, (i+2) * Fonts.base.height, choice->string);
+        else
+            x11_draw_utf8(&Fonts, CLR_BASE1, CLR_BASE03, 0, (i+2) * Fonts.base.height, choice->string);
+    }
 }
 
 static void mouse_input(MouseAct act, MouseBtn btn, int x, int y) {
@@ -49,18 +179,47 @@ static void mouse_input(MouseAct act, MouseBtn btn, int x, int y) {
 }
 
 static void keyboard_input(uint32_t key) {
-    (void)key;
+    switch (key) {
+        case KEY_UP:
+            if (ChoiceIdx > 0) ChoiceIdx--;
+            break;
+        case KEY_DOWN:
+            if (ChoiceIdx+1 < vec_size(&Choices)) ChoiceIdx++;
+            break;
+        case KEY_ESCAPE:
+            ChoiceIdx = SIZE_MAX;
+            // fall-through
+        case '\n': case '\r':
+            x11_deinit();
+            break;
+        case '\b':
+            if (Pos > 0)
+                buf_del(&Query, --Pos);
+            break;
+        case RUNE_ERR:
+            break;
+        default:
+            ChoiceIdx = 0;
+            buf_ins(&Query, Pos++, key);
+            break;
+    }
+    score();
 }
 
 int main(int argc, char** argv) {
-    /* load the buffer */
-    buf_init(&Buffer);
-    buf_setlocked(&Buffer, false);
+    load_choices();
+    /* initialize the filter edit buffer */
+    buf_init(&Query);
+    buf_setlocked(&Query, false);
     /* initialize the display engine */
     x11_init(&Config);
-    x11_window("pick", Width, Height);
+    x11_dialog("pick", Width, Height);
     x11_show();
     x11_font_load(&Fonts, FONTNAME);
     x11_loop();
+    /* print out the choice */
+    Choice* choice = (Choice*)vec_at(&Choices, ChoiceIdx);
+    if (vec_size(&Choices) && ChoiceIdx != SIZE_MAX)
+        puts(choice->string);
     return 0;
 }