]> git.mdlowis.com Git - projs/tide.git/commitdiff
Removed junk files from syncthing
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 24 May 2017 23:58:32 +0000 (19:58 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 24 May 2017 23:58:32 +0000 (19:58 -0400)
inc/win.sync-conflict-20170524-185737.h [deleted file]
inc/x11.sync-conflict-20170524-185739.h [deleted file]
lib/win.sync-conflict-20170524-185738.c [deleted file]
lib/x11.sync-conflict-20170524-185739.c [deleted file]
xedit.sync-conflict-20170524-185737.c [deleted file]

diff --git a/inc/win.sync-conflict-20170524-185737.h b/inc/win.sync-conflict-20170524-185737.h
deleted file mode 100644 (file)
index 77b464a..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-enum {
-    MouseLeft    = 1,
-    MouseMiddle  = 2,
-    MouseRight   = 3,
-    MouseWheelUp = 4,
-    MouseWheelDn = 5
-};
-
-typedef enum {
-    STATUS   = 0,
-    TAGS     = 1,
-    EDIT     = 2,
-    SCROLL   = 3,
-    NREGIONS = 4,
-    FOCUSED  = 4
-} WinRegion;
-
-typedef struct {
-    int mods;
-    Rune key;
-    void (*action)(void);
-} KeyBinding;
-
-typedef struct {
-    size_t x;
-    size_t y;
-    size_t height;
-    size_t width;
-    size_t csrx;
-    size_t csry;
-    bool warp_ptr;
-    View view;
-} Region;
-
-typedef void (*MouseFunc)(WinRegion id, size_t count, size_t row, size_t col);
-
-typedef struct {
-    MouseFunc left;
-    MouseFunc middle;
-    MouseFunc right;
-} MouseConfig;
-
-void win_window(char* name, void (*errfn)(char*));
-void win_dialog(char* name, void (*errfn)(char*));
-void win_loop(void);
-void win_settext(WinRegion id, char* text);
-void win_setruler(size_t ruler);
-void win_setkeys(KeyBinding* bindings);
-void win_setmouse(MouseConfig* mconfig);
-void win_warpptr(WinRegion id);
-View* win_view(WinRegion id);
-Buf* win_buf(WinRegion id);
-Sel* win_sel(WinRegion id);
-bool win_btnpressed(int btn);
-WinRegion win_getregion(void);
-bool win_setregion(WinRegion id);
-void win_setscroll(double offset, double visible);
-
-/* These functions must be implemented by any appliation that wishes
-   to use this module */
-void onshutdown(void);
-void onfocus(bool focused);
-void onupdate(void);
-void onlayout(void);
-void onscroll(double percent);
-void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col);
-void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col);
-void onmouseright(WinRegion id, bool pressed, size_t row, size_t col);
-
diff --git a/inc/x11.sync-conflict-20170524-185739.h b/inc/x11.sync-conflict-20170524-185739.h
deleted file mode 100644 (file)
index a758842..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-typedef struct {
-    void (*redraw)(int width, int height);
-    void (*handle_key)(int mods, uint32_t rune);
-    void (*shutdown)(void);
-    void (*set_focus)(bool focus);
-    void (*mouse_drag)(int state, int x, int y);
-    void (*mouse_btn)(int state, bool pressed, int x, int y);
-    uint32_t palette[16];
-} XConfig;
-
-typedef void* XFont;
-
-typedef struct {
-    uint32_t attr; /* attributes  applied to this cell */
-    uint32_t rune; /* rune value for the cell */
-} XGlyph;
-
-typedef struct {
-    void* font;
-    uint32_t glyph;
-    short x;
-    short y;
-} XGlyphSpec;
-
-/* key definitions */
-enum Keys {
-    /* Define some runes in the private use area of unicode to represent
-     * special keys */
-    KEY_F1     = (0xE000+0),
-    KEY_F2     = (0xE000+1),
-    KEY_F3     = (0xE000+2),
-    KEY_F4     = (0xE000+3),
-    KEY_F5     = (0xE000+4),
-    KEY_F6     = (0xE000+5),
-    KEY_F7     = (0xE000+6),
-    KEY_F8     = (0xE000+7),
-    KEY_F9     = (0xE000+8),
-    KEY_F10    = (0xE000+9),
-    KEY_F11    = (0xE000+10),
-    KEY_F12    = (0xE000+11),
-    KEY_INSERT = (0xE000+12),
-    KEY_DELETE = (0xE000+13),
-    KEY_HOME   = (0xE000+14),
-    KEY_END    = (0xE000+15),
-    KEY_PGUP   = (0xE000+16),
-    KEY_PGDN   = (0xE000+17),
-    KEY_UP     = (0xE000+18),
-    KEY_DOWN   = (0xE000+19),
-    KEY_RIGHT  = (0xE000+20),
-    KEY_LEFT   = (0xE000+21),
-
-    /* ASCII Control Characters */
-    KEY_CTRL_TILDE       = 0x00,
-    KEY_CTRL_2           = 0x00,
-    KEY_CTRL_A           = 0x01,
-    KEY_CTRL_B           = 0x02,
-    KEY_CTRL_C           = 0x03,
-    KEY_CTRL_D           = 0x04,
-    KEY_CTRL_E           = 0x05,
-    KEY_CTRL_F           = 0x06,
-    KEY_CTRL_G           = 0x07,
-    KEY_BACKSPACE        = 0x08,
-    KEY_CTRL_H           = 0x08,
-    KEY_TAB              = 0x09,
-    KEY_CTRL_I           = 0x09,
-    KEY_CTRL_J           = 0x0A,
-    KEY_CTRL_K           = 0x0B,
-    KEY_CTRL_L           = 0x0C,
-    KEY_ENTER            = 0x0D,
-    KEY_CTRL_M           = 0x0D,
-    KEY_CTRL_N           = 0x0E,
-    KEY_CTRL_O           = 0x0F,
-    KEY_CTRL_P           = 0x10,
-    KEY_CTRL_Q           = 0x11,
-    KEY_CTRL_R           = 0x12,
-    KEY_CTRL_S           = 0x13,
-    KEY_CTRL_T           = 0x14,
-    KEY_CTRL_U           = 0x15,
-    KEY_CTRL_V           = 0x16,
-    KEY_CTRL_W           = 0x17,
-    KEY_CTRL_X           = 0x18,
-    KEY_CTRL_Y           = 0x19,
-    KEY_CTRL_Z           = 0x1A,
-    KEY_ESCAPE           = 0x1B,
-    KEY_CTRL_LSQ_BRACKET = 0x1B,
-    KEY_CTRL_3           = 0x1B,
-    KEY_CTRL_4           = 0x1C,
-    KEY_CTRL_BACKSLASH   = 0x1C,
-    KEY_CTRL_5           = 0x1D,
-    KEY_CTRL_RSQ_BRACKET = 0x1D,
-    KEY_CTRL_6           = 0x1E,
-    KEY_CTRL_7           = 0x1F,
-    KEY_CTRL_SLASH       = 0x1F,
-    KEY_CTRL_UNDERSCORE  = 0x1F,
-};
-
-/* Key modifier masks */
-enum {
-    ModNone       = 0,
-    ModShift      = (1 << 0),
-    ModCapsLock   = (1 << 1),
-    ModCtrl       = (1 << 2),
-    ModAlt        = (1 << 3),
-    ModNumLock    = (1 << 4),
-    ModScrollLock = (1 << 5),
-    ModWindows    = (1 << 6),
-    ModAny        = -1
-};
-
-/* Selection identifiers */
-enum {
-    PRIMARY   = 0,
-    CLIPBOARD = 1
-};
-
-void x11_init(XConfig* cfg);
-void x11_deinit(void);
-int x11_keybtnstate(void);
-bool x11_keymodsset(int mask);
-void x11_window(char* name, int width, int height);
-void x11_dialog(char* name, int height, int width);
-void x11_show(void);
-bool x11_running(void);
-void x11_flip(void);
-void x11_flush(void);
-void x11_finish(void);
-
-int x11_events_queued(void);
-bool x11_events_await(unsigned int ms);
-void x11_events_take(void);
-
-void x11_mouse_get(int* x, int* y);
-void x11_mouse_set(int x, int y);
-
-XFont x11_font_load(char* name);
-size_t x11_font_height(XFont fnt);
-size_t x11_font_width(XFont fnt);
-size_t x11_font_descent(XFont fnt);
-void x11_font_getglyph(XFont font, XGlyphSpec* spec, uint32_t rune);
-size_t x11_font_getglyphs(XGlyphSpec* specs, const XGlyph* glyphs, int len, XFont font, int x, int y);
-
-void x11_draw_rect(int color, int x, int y, int width, int height);
-void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str);
-void x11_draw_glyphs(int fg, int bg, XGlyphSpec* glyphs, size_t nglyphs);
-void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str);
-
-bool x11_sel_get(int selid, void(*cbfn)(char*));
-bool x11_sel_set(int selid, char* str);
-
diff --git a/lib/win.sync-conflict-20170524-185738.c b/lib/win.sync-conflict-20170524-185738.c
deleted file mode 100644 (file)
index f6cfc62..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-#include <stdc.h>
-#include <utf.h>
-#include <edit.h>
-#include <x11.h>
-#include <win.h>
-#include <ctype.h>
-
-static void onredraw(int height, int width);
-static void oninput(int mods, Rune key);
-static void onmousedrag(int state, int x, int y);
-static void onmousebtn(int btn, bool pressed, int x, int y);
-static void onwheelup(WinRegion id, bool pressed, size_t row, size_t col);
-static void onwheeldn(WinRegion id, bool pressed, size_t row, size_t col);
-static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols);
-static WinRegion getregion(size_t x, size_t y);
-
-static size_t Ruler = 0;
-static double ScrollOffset = 0.0;
-static double ScrollVisible = 1.0;
-static XFont Font;
-static XConfig Config = {
-    .redraw       = onredraw,
-    .handle_key   = oninput,
-    .shutdown     = onshutdown,
-    .set_focus    = onfocus,
-    .mouse_drag   = onmousedrag,
-    .mouse_btn    = onmousebtn,
-    .palette      = COLOR_PALETTE
-};
-static WinRegion Focused = EDIT;
-static Region Regions[NREGIONS] = {0};
-KeyBinding* Keys = NULL;
-
-static void win_init(void (*errfn)(char*)) {
-    for (int i = 0; i < SCROLL; i++)
-        view_init(&(Regions[i].view), NULL, errfn);
-    x11_init(&Config);
-    Font = x11_font_load(FONTNAME);
-}
-
-void win_window(char* name, void (*errfn)(char*)) {
-    win_init(errfn);
-    x11_window(name, Width, Height);
-}
-
-void win_dialog(char* name, void (*errfn)(char*)) {
-    win_init(errfn);
-    x11_dialog(name, Width, Height);
-}
-
-static bool update_focus(void) {
-    static int prev_x = 0, prev_y = 0;
-    int ptr_x, ptr_y;
-    bool changed = false;
-    /* dont change focus if any mouse buttons are pressed */
-    if ((x11_keybtnstate() & 0x1f00) == 0) {
-        x11_mouse_get(&ptr_x, &ptr_y);
-        if (prev_x != ptr_x || prev_y != ptr_y)
-            changed = win_setregion(getregion(ptr_x, ptr_y));
-        prev_x = ptr_x, prev_y = ptr_y;
-    }
-    return changed;
-}
-
-void win_loop(void) {
-    x11_show();
-    x11_flip();
-    while (x11_running()) {
-        bool pending = x11_events_await(EventTimeout);
-        int nevents  = x11_events_queued();
-        if (update_focus() || pending || nevents) {
-            x11_events_take();
-            if (x11_running())
-                x11_flip();
-        }
-        x11_flush();
-    }
-    x11_finish();
-}
-
-void win_settext(WinRegion id, char* text) {
-    View* view = win_view(id);
-    view->buffer.gapstart = view->buffer.bufstart;
-    view->buffer.gapend   = view->buffer.bufend;
-    view->selection = (Sel){0,0,0};
-    view_putstr(view, text);
-    view_selprev(view); // clear the selection
-    buf_logclear(&(view->buffer));
-}
-
-void win_setruler(size_t ruler) {
-    Ruler = ruler;
-}
-
-void win_setkeys(KeyBinding* bindings) {
-    Keys = bindings;
-}
-
-bool win_btnpressed(int btn) {
-    int btnmask = (1 << (btn + 7));
-    return ((x11_keybtnstate() & btnmask) == btnmask);
-}
-
-WinRegion win_getregion(void) {
-    return Focused;
-}
-
-bool win_setregion(WinRegion id) {
-    bool changed = true;
-    if (Focused != id && (id == TAGS || id == EDIT))
-        changed = true, Focused = id;
-    return changed;
-}
-
-void win_warpptr(WinRegion id) {
-    Regions[id].warp_ptr = true;
-}
-
-View* win_view(WinRegion id) {
-    if (id == FOCUSED) id = Focused;
-    return &(Regions[id].view);
-}
-
-Buf* win_buf(WinRegion id) {
-    if (id == FOCUSED) id = Focused;
-    return &(Regions[id].view.buffer);
-}
-
-Sel* win_sel(WinRegion id) {
-    if (id == FOCUSED) id = Focused;
-    return &(Regions[id].view.selection);
-}
-
-void win_setscroll(double offset, double visible) {
-    ScrollOffset  = offset;
-    ScrollVisible = visible;
-}
-
-static void layout(int width, int height) {
-    size_t fheight = x11_font_height(Font);
-    size_t fwidth  = x11_font_width(Font);
-    View* statview = win_view(STATUS);
-    View* tagview  = win_view(TAGS);
-    View* editview = win_view(EDIT);
-
-    /* update the text views and region positions and sizes */
-    for (int i = 0; i < SCROLL; i++) {
-        Regions[i].x      = 2;
-        Regions[i].y      = 2;
-        Regions[i].csrx   = SIZE_MAX;
-        Regions[i].csry   = SIZE_MAX;
-        Regions[i].width  = (width - 4);
-        Regions[i].height = fheight;
-    }
-
-    /* place the status region */
-    view_resize(statview, 1, Regions[STATUS].width / fwidth);
-
-    /* Place the tag region relative to status */
-    Regions[TAGS].y = 5 + Regions[STATUS].y + Regions[STATUS].height;
-    size_t maxtagrows = ((height - Regions[TAGS].y - 5) / 4) / fheight;
-    size_t tagcols    = Regions[TAGS].width / fwidth;
-    size_t tagrows    = view_limitrows(tagview, maxtagrows, tagcols);
-    Regions[TAGS].height = tagrows * fheight;
-    view_resize(tagview, tagrows, tagcols);
-
-    /* Place the scroll region relative to tags */
-    Regions[SCROLL].x      = 0;
-    Regions[SCROLL].y      = 5 + Regions[TAGS].y + Regions[TAGS].height;
-    Regions[SCROLL].height = (height - Regions[EDIT].y - 5);
-    Regions[SCROLL].width  = 5 + fwidth;
-
-    /* Place the edit region relative to tags */
-    Regions[EDIT].x      = 3 + Regions[SCROLL].width;
-    Regions[EDIT].y      = 5 + Regions[TAGS].y + Regions[TAGS].height;
-    Regions[EDIT].height = (height - Regions[EDIT].y - 5);
-    Regions[EDIT].width  = width - Regions[SCROLL].width - 5;
-    view_resize(editview, Regions[EDIT].height / fheight, Regions[EDIT].width / fwidth);
-}
-
-static void onredraw(int width, int height) {
-    size_t fheight = x11_font_height(Font);
-    size_t fwidth  = x11_font_width(Font);
-
-    layout(width, height);
-    onupdate(); // Let the user program update the status and other content
-    view_update(win_view(STATUS), &(Regions[STATUS].csrx), &(Regions[STATUS].csry));
-    view_update(win_view(TAGS), &(Regions[TAGS].csrx), &(Regions[TAGS].csry));
-    view_update(win_view(EDIT), &(Regions[EDIT].csrx), &(Regions[EDIT].csry));
-    onlayout(); // Let the user program update the scroll bar
-
-    for (int i = 0; i < SCROLL; i++) {
-        View* view = win_view(i);
-        x11_draw_rect((i == TAGS ? CLR_BASE02 : CLR_BASE03),
-            0, Regions[i].y - 3, width, Regions[i].height + 8);
-        x11_draw_rect(CLR_BASE01, 0, Regions[i].y - 3, width, 1);
-        if ((i == EDIT) && (Ruler != 0))
-            x11_draw_rect(CLR_BASE02, (Ruler+2) * fwidth, Regions[i].y-2, 1, Regions[i].height+7);
-        for (size_t y = 0; y < view->nrows; y++) {
-            Row* row = view_getrow(view, y);
-            draw_glyphs(Regions[i].x, Regions[i].y + ((y+1) * fheight), row->cols, row->rlen, row->len);
-        }
-    }
-
-    /* draw the scroll region */
-    size_t thumbreg = (Regions[SCROLL].height - Regions[SCROLL].y + 9);
-    size_t thumboff = (size_t)((thumbreg * ScrollOffset) + (Regions[SCROLL].y - 2));
-    size_t thumbsz  = (size_t)(thumbreg * ScrollVisible);
-    if (thumbsz < 5) thumbsz = 5;
-    x11_draw_rect(CLR_BASE01, Regions[SCROLL].width, Regions[SCROLL].y - 2, 1, Regions[SCROLL].height);
-    x11_draw_rect(CLR_BASE00, 0, Regions[SCROLL].y - 2, Regions[SCROLL].width, thumbreg);
-    x11_draw_rect(CLR_BASE03, 0, thumboff, Regions[SCROLL].width, thumbsz);
-
-    /* place the cursor on screen */
-    if (Regions[Focused].csrx != SIZE_MAX && Regions[Focused].csry != SIZE_MAX) {
-        x11_draw_rect(CLR_BASE3,
-            Regions[Focused].x + (Regions[Focused].csrx * fwidth),
-            Regions[Focused].y + (Regions[Focused].csry * fheight),
-            1, fheight);
-    }
-
-    /* adjust the mouse location */
-    if (Regions[Focused].warp_ptr) {
-        Regions[Focused].warp_ptr = false;
-        size_t x = Regions[Focused].x + (Regions[Focused].csrx * fwidth)  - (fwidth/2);
-        size_t y = Regions[Focused].y + (Regions[Focused].csry * fheight) + (fheight/2);
-        x11_mouse_set(x, y);
-    }
-}
-
-static void oninput(int mods, Rune key) {
-    /* mask of modifiers we don't care about */
-    mods = mods & (ModCtrl|ModAlt|ModShift);
-    /* handle the proper line endings */
-    if (key == '\r') key = '\n';
-    /* search for a key binding entry */
-    uint32_t mkey = tolower(key);
-    for (KeyBinding* bind = Keys; bind && bind->key; bind++) {
-        if ((mkey == bind->key) && (bind->mods == ModAny || bind->mods == mods)) {
-            bind->action();
-            return;
-        }
-    }
-
-    /* fallback to just inserting the rune if it doesn't fall in the private use area.
-     * the private use area is used to encode special keys */
-    if (key < 0xE000 || key > 0xF8FF) {
-        if (key == '\n' && win_view(FOCUSED)->buffer.crlf)
-            key = RUNE_CRLF;
-        view_insert(win_view(FOCUSED), true, key);
-    }
-}
-
-static void scroll_actions(int btn, bool pressed, int x, int y) {
-    size_t row = (y-Regions[SCROLL].y) / x11_font_height(Font);
-    size_t col = (x-Regions[SCROLL].x) / x11_font_width(Font);
-    switch (btn) {
-        case MouseLeft:
-            if (pressed)
-                view_scroll(win_view(EDIT), -row);
-            break;
-        case MouseMiddle:
-            if (pressed)
-                onscroll((double)(y - Regions[SCROLL].y) /
-                         (double)(Regions[SCROLL].height - Regions[SCROLL].y));
-            break;
-        case MouseRight:
-            if (pressed)
-                view_scroll(win_view(EDIT), +row);
-            break;
-        case MouseWheelUp:
-            view_scroll(win_view(EDIT), -ScrollLines);
-            break;
-        case MouseWheelDn:
-            view_scroll(win_view(EDIT), +ScrollLines);
-            break;
-    }
-}
-
-static void onmousedrag(int state, int x, int y) {
-    WinRegion id = getregion(x, y);
-    size_t row = (y-Regions[id].y) / x11_font_height(Font);
-    size_t col = (x-Regions[id].x) / x11_font_width(Font);
-    if (id == Focused && win_btnpressed(MouseLeft))
-        view_selext(win_view(id), row, col);
-}
-
-static void onmousebtn(int btn, bool pressed, int x, int y) {
-    WinRegion id = getregion(x, y);
-    size_t row = (y-Regions[id].y) / x11_font_height(Font);
-    size_t col = (x-Regions[id].x) / x11_font_width(Font);
-
-    if (id == SCROLL) {
-        scroll_actions(btn, pressed, x, y);
-    } else {
-        switch(btn) {
-            case MouseLeft:    onmouseleft(id, pressed, row, col);   break;
-            case MouseMiddle:  onmousemiddle(id, pressed, row, col); break;
-            case MouseRight:   onmouseright(id, pressed, row, col);  break;
-            case MouseWheelUp: onwheelup(id, pressed, row, col);     break;
-            case MouseWheelDn: onwheeldn(id, pressed, row, col);     break;
-        }
-    }
-}
-
-static void onwheelup(WinRegion id, bool pressed, size_t row, size_t col) {
-    if (!pressed) return;
-    view_scroll(win_view(id), -ScrollLines);
-}
-
-static void onwheeldn(WinRegion id, bool pressed, size_t row, size_t col) {
-    if (!pressed) return;
-    view_scroll(win_view(id), +ScrollLines);
-}
-
-static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols) {
-    XGlyphSpec specs[rlen];
-    size_t i = 0;
-    while (rlen && i < ncols) {
-        int numspecs = 0;
-        uint32_t attr = glyphs[i].attr;
-        while (i < ncols && glyphs[i].attr == attr) {
-            x11_font_getglyph(Font, &(specs[numspecs]), glyphs[i].rune);
-            specs[numspecs].x = x;
-            specs[numspecs].y = y - x11_font_descent(Font);
-            x += x11_font_width(Font);
-            numspecs++;
-            i++;
-            /* skip over null chars which mark multi column runes */
-            for (; i < ncols && !glyphs[i].rune; i++)
-                x += x11_font_width(Font);
-        }
-        /* Draw the glyphs with the proper colors */
-        uint8_t bg = attr >> 8;
-        uint8_t fg = attr & 0xFF;
-        x11_draw_glyphs(fg, bg, specs, numspecs);
-        rlen -= numspecs;
-    }
-}
-
-static WinRegion getregion(size_t x, size_t y) {
-    for (int i = 0; i < NREGIONS; i++) {
-        size_t startx = Regions[i].x, endx = startx + Regions[i].width;
-        size_t starty = Regions[i].y, endy = starty + Regions[i].height;
-        if ((startx <= x && x <= endx) && (starty <= y && y <= endy))
-            return (WinRegion)i;
-    }
-    return NREGIONS;
-}
diff --git a/lib/x11.sync-conflict-20170524-185739.c b/lib/x11.sync-conflict-20170524-185739.c
deleted file mode 100644 (file)
index 38d3dc1..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xft/Xft.h>
-#include <stdc.h>
-#include <x11.h>
-#include <utf.h>
-#include <edit.h>
-#include <locale.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-static struct XSel* selfetch(Atom atom);
-static void selclear(XEvent* evnt);
-static void selnotify(XEvent* evnt);
-static void selrequest(XEvent* evnt);
-
-struct XFont {
-    struct {
-        int height;
-        int width;
-        int ascent;
-        int descent;
-        XftFont* match;
-        FcFontSet* set;
-        FcPattern* pattern;
-    } base;
-    struct {
-        XftFont* font;
-        uint32_t unicodep;
-    } cache[FontCacheSize];
-    int ncached;
-};
-
-static bool Running = true;
-static struct {
-    Window root;
-    Display* display;
-    Visual* visual;
-    Colormap colormap;
-    unsigned depth;
-    int screen;
-    /* assume a single window for now. these are it's attributes */
-    Window window;
-    XftDraw* xft;
-    Pixmap pixmap;
-    int width;
-    int height;
-    XIC xic;
-    XIM xim;
-    GC gc;
-} X;
-static XConfig* Config;
-static int KeyBtnState;
-static Atom SelTarget;
-static struct XSel {
-    char* name;
-    Atom atom;
-    char* text;
-    void (*callback)(char*);
-} Selections[] = {
-    { .name = "PRIMARY" },
-    { .name = "CLIPBOARD" },
-};
-
-static void xftcolor(XftColor* xc, uint32_t c) {
-    xc->color.alpha = 0xFF | ((c & 0xFF000000) >> 16);
-    xc->color.red   = 0xFF | ((c & 0x00FF0000) >> 8);
-    xc->color.green = 0xFF | ((c & 0x0000FF00));
-    xc->color.blue  = 0xFF | ((c & 0x000000FF) << 8);
-    XftColorAllocValue(X.display, X.visual, X.colormap, &(xc->color), xc);
-}
-
-void x11_deinit(void) {
-    Running = false;
-}
-
-void x11_init(XConfig* cfg) {
-    atexit(x11_deinit);
-    signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal
-    setlocale(LC_CTYPE, "");
-    XSetLocaleModifiers("");
-    /* open the X display and get basic attributes */
-    Config = cfg;
-    if (!(X.display = XOpenDisplay(0)))
-        die("could not open display");
-    X.root = DefaultRootWindow(X.display);
-    XWindowAttributes wa;
-    XGetWindowAttributes(X.display, X.root, &wa);
-    X.visual   = wa.visual;
-    X.colormap = wa.colormap;
-    X.screen   = DefaultScreen(X.display);
-    X.depth    = DefaultDepth(X.display, X.screen);
-    /* initialize selection atoms */
-    for (int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++)
-        Selections[i].atom = XInternAtom(X.display, Selections[i].name, 0);
-    SelTarget = XInternAtom(X.display, "UTF8_STRING", 0);
-    if (SelTarget == None)
-        SelTarget = XInternAtom(X.display, "STRING", 0);
-}
-
-int x11_keybtnstate(void) {
-    return KeyBtnState;
-}
-
-bool x11_keymodsset(int mask) {
-    return ((KeyBtnState & mask) == mask);
-}
-
-void x11_window(char* name, int width, int height) {
-    /* create the main window */
-    X.width  = width ;
-    X.height = height;
-    XWindowAttributes wa;
-    XGetWindowAttributes(X.display, X.root, &wa);
-    X.window = XCreateSimpleWindow(X.display, X.root,
-        (wa.width  - X.width) / 2,
-        (wa.height - X.height) /2,
-        X.width,
-        X.height,
-        0, X.depth,
-        Config->palette[0]);
-
-    /* register interest in the delete window message */
-    Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
-    XSetWMProtocols(X.display, X.window, &wmDeleteMessage, 1);
-
-    /* setup window attributes and events */
-    XSetWindowAttributes swa;
-    swa.backing_store = WhenMapped;
-    swa.bit_gravity = NorthWestGravity;
-    XChangeWindowAttributes(X.display, X.window, CWBackingStore|CWBitGravity, &swa);
-    XStoreName(X.display, X.window, name);
-    XSelectInput(X.display, X.window,
-          StructureNotifyMask
-        | ButtonPressMask
-        | ButtonReleaseMask
-        | ButtonMotionMask
-        | KeyPressMask
-        | FocusChangeMask
-    );
-
-    /* set input methods */
-    if ((X.xim = XOpenIM(X.display, 0, 0, 0)))
-        X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.window, XNFocusWindow, X.window, NULL);
-
-    /* initialize pixmap and drawing context */
-    X.pixmap = XCreatePixmap(X.display, X.window, width, height, X.depth);
-    X.xft    = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap);
-
-    /* initialize the graphics context */
-    XGCValues gcv;
-    gcv.foreground = WhitePixel(X.display, X.screen);
-    gcv.graphics_exposures = False;
-    X.gc = XCreateGC(X.display, X.window, GCForeground|GCGraphicsExposures, &gcv);
-}
-
-void x11_dialog(char* name, int height, int width) {
-    x11_window(name, height, width);
-    Atom WindowType = XInternAtom(X.display, "_NET_WM_WINDOW_TYPE", False);
-    Atom DialogType = XInternAtom(X.display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
-    XChangeProperty(X.display, X.window, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1);
-}
-
-void x11_show(void) {
-    /* simulate an initial resize and map the window */
-    XConfigureEvent ce;
-    ce.type   = ConfigureNotify;
-    ce.width  = X.width;
-    ce.height = X.height;
-    XSendEvent(X.display, X.window, False, StructureNotifyMask, (XEvent *)&ce);
-    XMapWindow(X.display, X.window);
-}
-
-bool x11_running(void) {
-    return Running;
-}
-
-void x11_flip(void) {
-    Config->redraw(X.width, X.height);
-    XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0);
-    x11_flush();
-}
-
-void x11_flush(void) {
-    XFlush(X.display);
-}
-
-void x11_finish(void) {
-    XCloseDisplay(X.display);
-    /* we're exiting now. If we own the clipboard, make sure it persists */
-    if (Selections[CLIPBOARD].text)
-        cmdwrite((char*[]){ "xcpd", NULL }, Selections[CLIPBOARD].text, NULL);
-}
-
-/******************************************************************************/
-
-static uint32_t special_keys(uint32_t key) {
-    switch (key) {
-        case XK_F1:        return KEY_F1;
-        case XK_F2:        return KEY_F2;
-        case XK_F3:        return KEY_F3;
-        case XK_F4:        return KEY_F4;
-        case XK_F5:        return KEY_F5;
-        case XK_F6:        return KEY_F6;
-        case XK_F7:        return KEY_F7;
-        case XK_F8:        return KEY_F8;
-        case XK_F9:        return KEY_F9;
-        case XK_F10:       return KEY_F10;
-        case XK_F11:       return KEY_F11;
-        case XK_F12:       return KEY_F12;
-        case XK_Insert:    return KEY_INSERT;
-        case XK_Delete:    return KEY_DELETE;
-        case XK_Home:      return KEY_HOME;
-        case XK_End:       return KEY_END;
-        case XK_Page_Up:   return KEY_PGUP;
-        case XK_Page_Down: return KEY_PGDN;
-        case XK_Up:        return KEY_UP;
-        case XK_Down:      return KEY_DOWN;
-        case XK_Left:      return KEY_LEFT;
-        case XK_Right:     return KEY_RIGHT;
-        case XK_Escape:    return KEY_ESCAPE;
-        case XK_BackSpace: return '\b';
-        case XK_Tab:       return '\t';
-        case XK_Return:    return '\r';
-        case XK_Linefeed:  return '\n';
-
-        /* modifiers should not trigger key presses */
-        case XK_Scroll_Lock:
-        case XK_Shift_L:
-        case XK_Shift_R:
-        case XK_Control_L:
-        case XK_Control_R:
-        case XK_Caps_Lock:
-        case XK_Shift_Lock:
-        case XK_Meta_L:
-        case XK_Meta_R:
-        case XK_Alt_L:
-        case XK_Alt_R:
-        case XK_Super_L:
-        case XK_Super_R:
-        case XK_Hyper_L:
-        case XK_Hyper_R:
-            return RUNE_ERR;
-
-        /* if it ain't special, don't touch it */
-        default:
-            return key;
-    }
-}
-
-static uint32_t getkey(XEvent* e) {
-    uint32_t rune = RUNE_ERR;
-    size_t len = 0;
-    char buf[8];
-    KeySym key;
-    Status status;
-    /* Read the key string */
-    if (X.xic)
-        len = Xutf8LookupString(X.xic, &(e->xkey), buf, sizeof(buf), &key, &status);
-    else
-        len = XLookupString(&(e->xkey), buf, sizeof(buf), &key, 0);
-    /* if it's ascii, just return it */
-    if (key >= 0x20 && key <= 0x7F)
-        return (uint32_t)key;
-    /* decode it */
-    if (len > 0) {
-        len = 0;
-        for (int i = 0; i < 8 && !utf8decode(&rune, &len, buf[i]); i++);
-    }
-    /* translate special key codes into unicode codepoints */
-    rune = special_keys(key);
-    return rune;
-}
-
-static void handle_key(XEvent* event) {
-    uint32_t key = getkey(event);
-    KeyBtnState = event->xkey.state;
-    if (key == RUNE_ERR) return;
-    Config->handle_key(KeyBtnState, key);
-}
-
-static void handle_mouse(XEvent* e) {
-    KeyBtnState = e->xbutton.state;
-    int x = e->xbutton.x;
-    int y = e->xbutton.y;
-
-    if (e->type == MotionNotify) {
-        Config->mouse_drag(KeyBtnState, x, y);
-    } else {
-        if (e->type == ButtonRelease)
-            KeyBtnState &= ~(1 << (e->xbutton.button + 7));
-        else
-            KeyBtnState |= (1 << (e->xbutton.button + 7));
-        Config->mouse_btn(e->xbutton.button, (e->type == ButtonPress), x, y);
-    }
-}
-
-static void set_focus(bool focused) {
-    if (focused) {
-        if (X.xic) XSetICFocus(X.xic);
-    } else {
-        if (X.xic) XUnsetICFocus(X.xic);
-    }
-    Config->set_focus(focused);
-}
-
-void x11_handle_event(XEvent* e) {
-    Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
-    switch (e->type) {
-        case FocusIn:          set_focus(true);  break;
-        case FocusOut:         set_focus(false); break;
-        case KeyPress:         handle_key(e);    break;
-        case ButtonRelease:    handle_mouse(e);  break;
-        case ButtonPress:      handle_mouse(e);  break;
-        case MotionNotify:     handle_mouse(e);  break;
-        case SelectionClear:   selclear(e);      break;
-        case SelectionNotify:  selnotify(e);     break;
-        case SelectionRequest: selrequest(e);    break;
-        case ClientMessage:
-            if (e->xclient.data.l[0] == wmDeleteMessage)
-                Config->shutdown();
-            break;
-        case ConfigureNotify: // Resize the window
-            if (e->xconfigure.width != X.width || e->xconfigure.height != X.height) {
-                X.width  = e->xconfigure.width;
-                X.height = e->xconfigure.height;
-                X.pixmap = XCreatePixmap(X.display, X.window, X.width, X.height, X.depth);
-                X.xft    = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap);
-            }
-            break;
-    }
-}
-
-int x11_events_queued(void) {
-    return XEventsQueued(X.display, QueuedAfterFlush);
-}
-
-bool x11_events_await(unsigned int ms) {
-    fd_set fds;
-    int xfd = ConnectionNumber(X.display), redraw = 1;
-    /* configure for 100ms timeout */
-    struct timeval tv = { .tv_usec = ms * 1000 };
-    FD_ZERO(&fds);
-    FD_SET(xfd, &fds);
-    return (select(xfd+1, &fds, NULL, NULL, &tv) > 0);
-}
-
-void x11_events_take(void) {
-    XEvent e;
-    int nevents;
-    XGetMotionEvents(X.display, X.window, CurrentTime, CurrentTime, &nevents);
-    while (XPending(X.display)) {
-        XNextEvent(X.display, &e);
-        if (!XFilterEvent(&e, None))
-            x11_handle_event(&e);
-    }
-}
-
-void x11_mouse_set(int x, int y) {
-    XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y);
-}
-
-void x11_mouse_get(int* ptrx, int* ptry) {
-    Window xw; int x; unsigned int ux;
-    XQueryPointer(X.display, X.window, &xw, &xw, &x, &x, ptrx, ptry, &ux);
-}
-
-XFont x11_font_load(char* name) {
-    struct XFont* font = calloc(1, sizeof(struct XFont));
-    /* init the library and the base font pattern */
-    if (!FcInit())
-        die("Could not init fontconfig.\n");
-    FcPattern* pattern = FcNameParse((FcChar8 *)name);
-    if (!pattern)
-        die("can't open font %s\n", name);
-
-    /* load the base font */
-    FcResult result;
-    FcPattern* match = XftFontMatch(X.display, X.screen, pattern, &result);
-    if (!match || !(font->base.match = XftFontOpenPattern(X.display, match)))
-        die("could not load default font: %s", name);
-
-    /* get base font extents */
-    XGlyphInfo extents;
-    const FcChar8 ascii[] =
-        " !\"#$%&'()*+,-./0123456789:;<=>?"
-        "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
-        "`abcdefghijklmnopqrstuvwxyz{|}~";
-    XftTextExtentsUtf8(X.display, font->base.match, ascii, sizeof(ascii), &extents);
-    font->base.set     = NULL;
-    font->base.pattern = FcPatternDuplicate(pattern);
-    font->base.ascent  = font->base.match->ascent;
-    font->base.descent = font->base.match->descent;
-    font->base.height  = font->base.ascent + font->base.descent;
-    font->base.width   = ((extents.xOff + (sizeof(ascii) - 1)) / sizeof(ascii));
-    FcPatternDestroy(pattern);
-    return font;
-}
-
-size_t x11_font_height(XFont fnt) {
-    struct XFont* font = fnt;
-    return font->base.height;
-}
-
-size_t x11_font_width(XFont fnt) {
-    struct XFont* font = fnt;
-    return font->base.width;
-}
-
-size_t x11_font_descent(XFont fnt) {
-    struct XFont* font = fnt;
-    return font->base.descent;
-}
-
-void x11_draw_rect(int color, int x, int y, int width, int height) {
-    XftColor clr;
-    xftcolor(&clr, Config->palette[color]);
-    XftDrawRect(X.xft, &clr, x, y, width, height);
-    XftColorFree(X.display, X.visual, X.colormap, &clr);
-}
-
-void x11_font_getglyph(XFont fnt, XGlyphSpec* spec, uint32_t rune) {
-    struct XFont* font = fnt;
-    /* if the rune is in the base font, set it and return */
-    FT_UInt glyphidx = XftCharIndex(X.display, font->base.match, rune);
-    if (glyphidx) {
-        spec->font  = font->base.match;
-        spec->glyph = glyphidx;
-        return;
-    }
-    /* Otherwise check the cache */
-    for (int f = 0; f < font->ncached; f++) {
-        glyphidx = XftCharIndex(X.display, font->cache[f].font, rune);
-        /* Fond a suitable font or found a default font */
-        if (glyphidx || (!glyphidx && font->cache[f].unicodep == rune)) {
-            spec->font  = font->cache[f].font;
-            spec->glyph = glyphidx;
-            return;
-        }
-    }
-    /* if all other options fail, ask fontconfig for a suitable font */
-    FcResult fcres;
-    if (!font->base.set)
-        font->base.set = FcFontSort(0, font->base.pattern, 1, 0, &fcres);
-    FcFontSet* fcsets[]  = { font->base.set };
-    FcPattern* fcpattern = FcPatternDuplicate(font->base.pattern);
-    FcCharSet* fccharset = FcCharSetCreate();
-    FcCharSetAddChar(fccharset, rune);
-    FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
-    FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-    FcConfigSubstitute(0, fcpattern, FcMatchPattern);
-    FcDefaultSubstitute(fcpattern);
-    FcPattern* fontmatch = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres);
-    /* add the font to the cache and use it */
-    if (font->ncached >= FontCacheSize) {
-        font->ncached = FontCacheSize - 1;
-        XftFontClose(X.display, font->cache[font->ncached].font);
-    }
-    font->cache[font->ncached].font = XftFontOpenPattern(X.display, fontmatch);
-    font->cache[font->ncached].unicodep = rune;
-    spec->glyph = XftCharIndex(X.display, font->cache[font->ncached].font, rune);
-    spec->font  = font->cache[font->ncached].font;
-    font->ncached++;
-    FcPatternDestroy(fcpattern);
-    FcCharSetDestroy(fccharset);
-}
-
-size_t x11_font_getglyphs(XGlyphSpec* specs, const XGlyph* glyphs, int len, XFont fnt, int x, int y) {
-    struct XFont* font = fnt;
-    int winx = x, winy = y;
-    size_t numspecs = 0;
-    for (int i = 0, xp = winx, yp = winy + font->base.ascent; i < len;) {
-        x11_font_getglyph(font, &(specs[numspecs]), glyphs[i].rune);
-        specs[numspecs].x = xp;
-        specs[numspecs].y = yp;
-        xp += font->base.width;
-        numspecs++;
-        i++;
-        /* skip over null chars which mark multi column runes */
-        for (; i < len && !glyphs[i].rune; i++)
-            xp += font->base.width;
-    }
-    return numspecs;
-}
-
-void x11_draw_glyphs(int fg, int bg, XGlyphSpec* specs, size_t nspecs) {
-    if (!nspecs) return;
-    XftFont* font = specs[0].font;
-    XftColor fgc, bgc;
-    if (bg > 0) {
-        XGlyphInfo extent;
-        XftTextExtentsUtf8(X.display, font, (const FcChar8*)"0", 1, &extent);
-        int w = extent.xOff;
-        int h = (font->height - font->descent) + LineSpacing;
-        xftcolor(&bgc, Config->palette[bg]);
-        size_t width = specs[nspecs-1].x - specs[0].x + w;
-        x11_draw_rect(bg, specs[0].x, specs[0].y - h, width, font->height + LineSpacing);
-        XftColorFree(X.display, X.visual, X.colormap, &bgc);
-    }
-    xftcolor(&fgc, Config->palette[fg]);
-    XftDrawGlyphFontSpec(X.xft, &fgc, (XftGlyphFontSpec*)specs, nspecs);
-    XftColorFree(X.display, X.visual, X.colormap, &fgc);
-}
-
-void x11_draw_utf8(XFont fnt, int fg, int bg, int x, int y, char* str) {
-    struct XFont* font = fnt;
-    static XftGlyphFontSpec specs[256];
-    size_t nspecs = 0;
-    while (*str && nspecs < 256) {
-        x11_font_getglyph(font, (XGlyphSpec*)&(specs[nspecs]), *str);
-        specs[nspecs].x = x;
-        specs[nspecs].y = y;
-        x += font->base.width;
-        nspecs++;
-        str++;
-    }
-    x11_draw_glyphs(fg, bg, (XGlyphSpec*)specs, nspecs);
-}
-
-/* Selection Handling
- *****************************************************************************/
-
-static char* readprop(Display* disp, Window win, Atom prop) {
-    Atom type;
-    int format;
-    unsigned long nitems, nleft;
-    unsigned char* ret = NULL;
-    int nread = 1024;
-
-    // Read the property in progressively larger chunks until the entire
-    // property has been read (nleft == 0)
-    do {
-        if (ret) XFree(ret);
-        XGetWindowProperty(disp, win, prop, 0, nread, False, AnyPropertyType,
-                           &type, &format, &nitems, &nleft,
-                           &ret);
-        nread *= 2;
-    } while (nleft != 0);
-
-    return (char*)ret;
-}
-
-static struct XSel* selfetch(Atom atom) {
-    for (int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++)
-        if (atom == Selections[i].atom)
-            return &Selections[i];
-    return NULL;
-}
-
-static void selclear(XEvent* evnt) {
-    struct XSel* sel = selfetch(evnt->xselectionrequest.selection);
-    if (!sel) return;
-    free(sel->text);
-    sel->text = NULL;
-}
-
-static void selnotify(XEvent* evnt) {
-    /* bail if the selection cannot be converted */
-    if (evnt->xselection.property == None)
-        return;
-    struct XSel* sel = selfetch( evnt->xselection.selection );
-    char* propdata = readprop(X.display, X.window, sel->atom);
-    if (evnt->xselection.target == SelTarget) {
-        void(*cbfn)(char*) = sel->callback;
-        sel->callback = NULL;
-        cbfn(propdata);
-    }
-    /* cleanup */
-    if (propdata) XFree(propdata);
-}
-
-static void selrequest(XEvent* evnt) {
-    XEvent s;
-    struct XSel* sel = selfetch( evnt->xselectionrequest.selection );
-    s.xselection.type      = SelectionNotify;
-    s.xselection.property  = evnt->xselectionrequest.property;
-    s.xselection.requestor = evnt->xselectionrequest.requestor;
-    s.xselection.selection = evnt->xselectionrequest.selection;
-    s.xselection.target    = evnt->xselectionrequest.target;
-    s.xselection.time      = evnt->xselectionrequest.time;
-
-    Atom target    = evnt->xselectionrequest.target;
-    Atom xatargets = XInternAtom(X.display, "TARGETS", 0);
-    Atom xastring  = XInternAtom(X.display, "STRING", 0);
-    if (target == xatargets) {
-        /* respond with the supported type */
-        XChangeProperty(
-            X.display,
-            s.xselection.requestor,
-            s.xselection.property,
-            XA_ATOM, 32, PropModeReplace,
-            (unsigned char*)&SelTarget, 1);
-    } else if (target == SelTarget || target == xastring) {
-        XChangeProperty(
-            X.display,
-            s.xselection.requestor,
-            s.xselection.property,
-            SelTarget, 8, PropModeReplace,
-            (unsigned char*)sel->text, strlen(sel->text));
-    }
-    XSendEvent(X.display, s.xselection.requestor, True, 0, &s);
-}
-
-bool x11_sel_get(int selid, void(*cbfn)(char*)) {
-    struct XSel* sel = &(Selections[selid]);
-    if (sel->callback) return false;
-    Window owner = XGetSelectionOwner(X.display, sel->atom);
-    if (owner == X.window) {
-        cbfn(sel->text);
-    } else if (owner != None){
-        sel->callback = cbfn;
-        XConvertSelection(X.display, sel->atom, SelTarget, sel->atom, X.window, CurrentTime);
-    }
-    return true;
-}
-
-bool x11_sel_set(int selid, char* str) {
-    struct XSel* sel = &(Selections[selid]);
-    if (!sel || !str || !*str) {
-        free(str);
-        return false;
-    } else {
-        sel->text = str;
-        XSetSelectionOwner(X.display, sel->atom, X.window, CurrentTime);
-        return true;
-    }
-}
diff --git a/xedit.sync-conflict-20170524-185737.c b/xedit.sync-conflict-20170524-185737.c
deleted file mode 100644 (file)
index 0897ea9..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-#include <stdc.h>
-#include <x11.h>
-#include <utf.h>
-#include <edit.h>
-#include <ctype.h>
-#include <win.h>
-#include <shortcuts.h>
-
-typedef struct {
-    char* tag;
-    union {
-        void (*noarg)(void);
-        void (*arg)(char* arg);
-    } action;
-} Tag;
-
-/* The shell: Filled in with $SHELL. Used to execute commands */
-static char* ShellCmd[] = { NULL, "-c", NULL, NULL };
-static char* SedCmd[] = { "sed", "-e", NULL, NULL };
-static char* PickFileCmd[] = { "xfilepick", ".", NULL };
-static char* PickTagCmd[] = { "xtagpick", NULL, "tags", NULL, NULL };
-static char* OpenCmd[] = { "xedit", NULL, NULL };
-static Tag Builtins[];
-static int SearchDir = DOWN;
-static char* SearchTerm = NULL;
-
-/* Tag/Cmd Execution
- ******************************************************************************/
-static Tag* tag_lookup(char* cmd) {
-    size_t len = 0;
-    Tag* tags = Builtins;
-    for (char* tag = cmd; *tag && !isspace(*tag); tag++, len++);
-    while (tags->tag) {
-        if (!strncmp(tags->tag, cmd, len))
-            return tags;
-        tags++;
-    }
-    return NULL;
-}
-
-static void tag_exec(Tag* tag, char* arg) {
-    /* if we didnt get an arg, find one in the selection */
-    if (!arg) arg = view_getstr(win_view(TAGS), NULL);
-    if (!arg) arg = view_getstr(win_view(EDIT), NULL);
-    /* execute the tag handler */
-    tag->action.arg(arg);
-    free(arg);
-}
-
-static void cmd_exec(char* cmd) {
-    char op = '\0';
-    if (*cmd == ':' || *cmd == '!' || *cmd == '<' || *cmd == '|' || *cmd == '>')
-        op = *cmd, cmd++;
-    ShellCmd[2] = cmd;
-    /* execute the command */
-    char *input = NULL, *output = NULL, *error = NULL;
-    WinRegion dest = EDIT;
-    if (op && op != '<' && op != '!' && 0 == view_selsize(win_view(EDIT)))
-        win_view(EDIT)->selection = (Sel){ .beg = 0, .end = buf_end(win_buf(EDIT)) };
-    input = view_getstr(win_view(EDIT), NULL);
-
-    if (op == '!') {
-        cmdrun(ShellCmd, NULL);
-    } else if (op == '>') {
-        dest = TAGS;
-        output = cmdwriteread(ShellCmd, input, &error);
-    } else if (op == '|') {
-        output = cmdwriteread(ShellCmd, input, &error);
-    } else if (op == ':') {
-        SedCmd[2] = cmd;
-        output = cmdwriteread(SedCmd, input, &error);
-    } else {
-        if (op != '<') dest = win_getregion();
-        output = cmdread(ShellCmd, &error);
-    }
-
-    if (error)
-        view_append(win_view(TAGS), chomp(error));
-
-    if (output) {
-        if (op == '>')
-            view_append(win_view(dest), chomp(output));
-        else
-            view_putstr(win_view(dest), output);
-        win_setregion(dest);
-    }
-    /* cleanup */
-    free(input);
-    free(output);
-    free(error);
-}
-
-static void exec(char* cmd) {
-    /* skip leading space */
-    for (; *cmd && isspace(*cmd); cmd++);
-    if (!*cmd) return;
-    /* see if it matches a builtin tag */
-    Tag* tag = tag_lookup(cmd);
-    if (tag) {
-        while (*cmd && !isspace(*cmd++));
-        tag_exec(tag, (*cmd ? stringdup(cmd) : NULL));
-    } else {
-        cmd_exec(cmd);
-    }
-}
-
-/* Action Callbacks
- ******************************************************************************/
-static void onerror(char* msg) {
-    view_append(win_view(TAGS), msg);
-}
-
-static void trim_whitespace(void) {
-    Buf* buf = win_buf(EDIT);
-    if (TrimOnSave && buf_end(buf) > 0) {
-        View* view = win_view(EDIT);
-        unsigned off = 0, prev = 1;
-        /* loop through the buffer till we hit the end or we stop advancing */
-        while (off < buf_end(buf) && prev != off) {
-            off = buf_eol(buf, off);
-            Rune r = buf_get(buf, off-1);
-            for (; (r == ' ' || r == '\t'); r = buf_get(buf, off-1)) {
-                if (off <= view->selection.beg) {
-                    view->selection.end--;
-                    view->selection.beg--;
-                }
-                off = buf_delete(buf, off-1, off);
-            }
-            /* make sure we keep advancing */
-            prev = off;
-            off  = buf_byline(buf, off, +1);
-        }
-    }
-}
-
-static void quit(void) {
-    static uint64_t before = 0;
-    uint64_t now = getmillis();
-    if (!win_buf(EDIT)->modified || (now-before) <= 250) {
-        #ifndef TEST
-        x11_deinit();
-        #else
-        exit(0);
-        #endif
-    } else {
-        view_append(win_view(TAGS),
-            "File is modified. Repeat action twice in < 250ms to quit.");
-    }
-    before = now;
-}
-
-static bool changed_externally(Buf* buf) {
-    bool modified = (buf->modtime != modtime(buf->path));
-    if (modified) {
-        view_append(win_view(TAGS),
-            "File modified externally: Reload, Overwrite, or {SaveAs }");
-    }
-    return modified;
-}
-
-static void overwrite(void) {
-    trim_whitespace();
-    buf_save(win_buf(EDIT));
-}
-
-static void save(void) {
-    if (!changed_externally(win_buf(EDIT)))
-        overwrite();
-}
-
-static void reload(void) {
-    view_reload(win_view(EDIT));
-}
-
-/* Mouse Handling
- ******************************************************************************/
-void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col) {
-    static int count = 0;
-    static uint64_t before = 0;
-    if (!pressed) return;
-    uint64_t now = getmillis();
-    count = ((now-before) <= 250 ? count+1 : 1);
-    before = now;
-
-    if (count == 1) {
-        if (x11_keymodsset(ModShift))
-            view_selext(win_view(id), row, col);
-        else
-            view_setcursor(win_view(id), row, col);
-    } else if (count == 2) {
-        view_select(win_view(id), row, col);
-    } else if (count == 3) {
-        view_selword(win_view(id), row, col);
-    }
-}
-
-void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col) {
-    if (pressed) return;
-    if (win_btnpressed(MouseLeft)) {
-        cut();
-    } else {
-        char* str = view_fetch(win_view(id), row, col);
-        if (str) exec(str);
-        free(str);
-    }
-}
-
-void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) {
-    if (pressed) return;
-    if (win_btnpressed(MouseLeft)) {
-        paste();
-    } else {
-        SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1);
-        free(SearchTerm);
-        SearchTerm = view_fetch(win_view(id), row, col);
-        if (view_findstr(win_view(EDIT), SearchDir, SearchTerm)) {
-            win_setregion(EDIT);
-            win_warpptr(EDIT);
-        }
-    }
-}
-
-/* Keyboard Handling
- ******************************************************************************/
-static void saveas(char* arg) {
-    if (arg) {
-        char* path = win_buf(EDIT)->path;
-        win_buf(EDIT)->path = stringdup(arg);
-        buf_save(win_buf(EDIT));
-        free(path);
-    }
-}
-
-static void tag_undo(void) {
-    view_undo(win_view(EDIT));
-}
-
-static void tag_redo(void) {
-    view_redo(win_view(EDIT));
-}
-
-static void search(void) {
-    char* str;
-    SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1);
-    if (x11_keymodsset(ModAlt) && SearchTerm)
-        str = stringdup(SearchTerm);
-    else
-        str = view_getctx(win_view(FOCUSED));
-    view_findstr(win_view(EDIT), SearchDir, str);
-    free(SearchTerm);
-    SearchTerm = str;
-    if (view_selsize(win_view(EDIT))) {
-        win_setregion(EDIT);
-        win_warpptr(EDIT);
-    }
-}
-
-static void execute(void) {
-    char* str = view_getcmd(win_view(FOCUSED));
-    if (str) exec(str);
-    free(str);
-}
-
-static void find(char* arg) {
-    SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1);
-    view_findstr(win_view(EDIT), SearchDir, arg);
-}
-
-static void open_file(void) {
-    char* file = cmdread(PickFileCmd, NULL);
-    if (file) {
-        file = chomp(file);
-        if (!win_buf(EDIT)->path && !win_buf(EDIT)->modified) {
-            buf_load(win_buf(EDIT), file);
-        } else {
-            OpenCmd[1] = file;
-            cmdrun(OpenCmd, NULL);
-        }
-    }
-    free(file);
-}
-
-static void pick_symbol(char* symbol) {
-    PickTagCmd[1] = "fetch";
-    PickTagCmd[3] = symbol;
-    char* pick = cmdread(PickTagCmd, NULL);
-    if (pick) {
-        Buf* buf = win_buf(EDIT);
-        if (buf->path && 0 == strncmp(buf->path, pick, strlen(buf->path))) {
-            view_setln(win_view(EDIT), strtoul(strrchr(pick, ':')+1, NULL, 0));
-            win_setregion(EDIT);
-        } else {
-            if (!buf->path && !buf->modified) {
-                view_init(win_view(EDIT), pick, onerror);
-            } else {
-                OpenCmd[1] = chomp(pick);
-                cmdrun(OpenCmd, NULL);
-            }
-        }
-    }
-}
-
-static void pick_ctag(void) {
-    pick_symbol(NULL);
-}
-
-static void complete(void) {
-    View* view = win_view(FOCUSED);
-    buf_getword(&(view->buffer), risword, &(view->selection));
-    view->selection.end = buf_byrune(&(view->buffer), view->selection.end, RIGHT);
-    PickTagCmd[1] = "print";
-    PickTagCmd[3] = view_getstr(view, NULL);
-    char* pick = cmdread(PickTagCmd, NULL);
-    if (pick)
-        view_putstr(view, chomp(pick));
-    free(PickTagCmd[3]);
-}
-
-static void jump_to(char* arg) {
-    if (arg) {
-        size_t line = strtoul(arg, NULL, 0);
-        if (line) {
-            view_setln(win_view(EDIT), line);
-            win_setregion(EDIT);
-        } else {
-            pick_symbol(arg);
-        }
-    }
-}
-
-static void goto_ctag(void) {
-    char* str = view_getctx(win_view(FOCUSED));
-    jump_to(str);
-    free(str);
-}
-
-static void tabs(void) {
-    bool enabled = !(win_buf(EDIT)->expand_tabs);
-    win_buf(EDIT)->expand_tabs = enabled;
-    win_buf(TAGS)->expand_tabs = enabled;
-}
-
-static void indent(void) {
-    bool enabled = !(win_buf(EDIT)->copy_indent);
-    win_buf(EDIT)->copy_indent = enabled;
-    win_buf(TAGS)->copy_indent = enabled;
-}
-
-static void del_indent(void) {
-    view_indent(win_view(FOCUSED), LEFT);
-}
-
-static void add_indent(void) {
-    view_indent(win_view(FOCUSED), RIGHT);
-}
-
-static void eol_mode(void) {
-    int crlf = win_buf(EDIT)->crlf;
-    win_buf(EDIT)->crlf = !crlf;
-    win_buf(TAGS)->crlf = !crlf;
-    exec(crlf ? "|dos2unix" : "|unix2dos");
-}
-
-static void new_win(void) {
-    cmd_exec("!edit");
-}
-
-static void newline(void) {
-    View* view = win_view(FOCUSED);
-    if (x11_keymodsset(ModShift)) {
-        view_byline(view, UP, false);
-        view_bol(view, false);
-        if (view->selection.end == 0) {
-            view_insert(view, true, '\n');
-            view->selection = (Sel){0,0,0};
-            return;
-        }
-    }
-    view_eol(view, false);
-    view_insert(view, true, '\n');
-}
-
-void highlight(void) {
-    view_selctx(win_view(FOCUSED));
-}
-
-/* Main Routine
- ******************************************************************************/
-static Tag Builtins[] = {
-    { .tag = "Cut",       .action.noarg = cut       },
-    { .tag = "Copy",      .action.noarg = copy      },
-    { .tag = "Eol",       .action.noarg = eol_mode  },
-    { .tag = "Find",      .action.arg   = find      },
-    { .tag = "GoTo",      .action.arg   = jump_to   },
-    { .tag = "Indent",    .action.noarg = indent    },
-    { .tag = "Overwrite", .action.noarg = overwrite },
-    { .tag = "Paste",     .action.noarg = paste     },
-    { .tag = "Quit",      .action.noarg = quit      },
-    { .tag = "Redo",      .action.noarg = tag_redo  },
-    { .tag = "Reload",    .action.noarg = reload    },
-    { .tag = "Save",      .action.noarg = save      },
-    { .tag = "SaveAs",    .action.arg   = saveas    },
-    { .tag = "Tabs",      .action.noarg = tabs      },
-    { .tag = "Undo",      .action.noarg = tag_undo  },
-    { .tag = NULL,        .action.noarg = NULL      }
-};
-
-static KeyBinding Bindings[] = {
-    /* Cursor Movements */
-    { ModAny, KEY_HOME,  cursor_home  },
-    { ModAny, KEY_END,   cursor_end   },
-    { ModAny, KEY_UP,    cursor_up    },
-    { ModAny, KEY_DOWN,  cursor_dn    },
-    { ModAny, KEY_LEFT,  cursor_left  },
-    { ModAny, KEY_RIGHT, cursor_right },
-
-    /* Standard Unix Shortcuts */
-    { ModCtrl, 'u', del_to_bol  },
-    { ModCtrl, 'k', del_to_eol  },
-    { ModCtrl, 'w', del_to_bow  },
-    { ModCtrl, 'a', cursor_bol  },
-    { ModCtrl, 'e', cursor_eol  },
-
-    /* Standard Text Editing Shortcuts */
-    { ModCtrl, 's', save        },
-    { ModCtrl, 'z', undo        },
-    { ModCtrl, 'y', redo        },
-    { ModCtrl, 'x', cut         },
-    { ModCtrl, 'c', copy        },
-    { ModCtrl, 'v', paste       },
-    { ModCtrl, 'j', join_lines  },
-    { ModCtrl, 'l', select_line },
-
-    /* Block Indent */
-    { ModCtrl, '[', del_indent },
-    { ModCtrl, ']', add_indent },
-
-    /* Common Special Keys */
-    { ModNone, KEY_PGUP,      page_up   },
-    { ModNone, KEY_PGDN,      page_dn   },
-    { ModAny,  KEY_DELETE,    delete    },
-    { ModAny,  KEY_BACKSPACE, backspace },
-
-    /* Implementation Specific */
-    { ModNone,                 KEY_ESCAPE, select_prev  },
-    { ModCtrl,                 't',        change_focus },
-    { ModCtrl,                 'q',        quit         },
-    { ModCtrl,                 'h',        highlight    },
-    { ModCtrl,                 'f',        search       },
-    { ModCtrl|ModShift,        'f',        search       },
-    { ModCtrl|ModAlt,          'f',        search       },
-    { ModCtrl|ModAlt|ModShift, 'f',        search       },
-    { ModCtrl,                 'd',        execute      },
-    { ModCtrl,                 'o',        open_file    },
-    { ModCtrl,                 'p',        pick_ctag    },
-    { ModCtrl,                 'g',        goto_ctag    },
-    { ModCtrl,                 'n',        new_win      },
-    { ModCtrl,                 '\n',       newline      },
-    { ModCtrl|ModShift,        '\n',       newline      },
-    { ModCtrl,                 ' ',        complete     },
-    { 0, 0, 0 }
-};
-
-void onscroll(double percent) {
-    size_t bend = buf_end(win_buf(EDIT));
-    size_t off  = (size_t)((double)bend * percent);
-    view_scrollto(win_view(EDIT), (off >= bend ? bend : off));
-}
-
-void onfocus(bool focused) {
-    /* notify the user if the file has changed externally */
-    (void)changed_externally(win_buf(EDIT));
-}
-
-void onupdate(void) {
-    static char status_bytes[256];
-    memset(status_bytes, 0, sizeof(status_bytes));
-    char* status = status_bytes;
-    Buf* buf = win_buf(EDIT);
-    *(status++) = (buf->charset == BINARY ? 'B' : 'U');
-    *(status++) = (buf->crlf ? 'C' : 'N');
-    *(status++) = (buf->expand_tabs ? 'S' : 'T');
-    *(status++) = (buf->copy_indent ? 'I' : 'i');
-    *(status++) = (SearchDir < 0 ? '<' : '>');
-    *(status++) = (buf->modified ? '*' : ' ');
-    *(status++) = ' ';
-    char* path = (buf->path ? buf->path : "*scratch*");
-    size_t remlen = sizeof(status_bytes) - strlen(status_bytes) - 1;
-    strncat(status, path, remlen);
-    win_settext(STATUS, status_bytes);
-    win_view(STATUS)->selection = (Sel){0,0,0};
-}
-
-void onlayout(void) {
-    /* calculate and update scroll region */
-    View* view = win_view(EDIT);
-    size_t bend = buf_end(win_buf(EDIT));
-    if (bend == 0) bend = 1;
-    if (!view->rows) return;
-    size_t vbeg = view->rows[0]->off;
-    size_t vend = view->rows[view->nrows-1]->off + view->rows[view->nrows-1]->rlen;
-    double scroll_vis = (double)(vend - vbeg) / (double)bend;
-    double scroll_off = ((double)vbeg / (double)bend);
-    win_setscroll(scroll_off, scroll_vis);
-}
-
-void onshutdown(void) {
-    quit();
-}
-
-#ifndef TEST
-int main(int argc, char** argv) {
-    /* setup the shell */
-    ShellCmd[0] = getenv("SHELL");
-    if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh";
-    /* Create the window and enter the event loop */
-    win_window("edit", onerror);
-    char* tags = getenv("EDITTAGS");
-    win_settext(TAGS, (tags ? tags : DEFAULT_TAGS));
-    win_setruler(80);
-    view_init(win_view(EDIT), (argc > 1 ? argv[1] : NULL), onerror);
-    win_setkeys(Bindings);
-    win_loop();
-    return 0;
-}
-#endif