]> git.mdlowis.com Git - projs/tide.git/commitdiff
added view module in order to support multiple buffer views
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 14 Nov 2016 01:53:41 +0000 (20:53 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 14 Nov 2016 01:53:41 +0000 (20:53 -0500)
Makefile
inc/edit.h
inc/x11.h [moved from inc/X.h with 80% similarity]
libedit/clip.c [deleted file]
libedit/view.c [new file with mode: 0644]
libx/x11.c
xedit.c
xpick.c

index ae1e2b49b6274b88c8208eb9b83dbe9adbd5bc32..34d6c54b0e90501a727c11b3de68730e586ab6d1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ LIBEDIT_OBJS =         \
        libedit/utf8.o     \
        libedit/utils.o    \
        libedit/exec.o     \
-       libedit/clip.o
+       libedit/view.o
 
 LIBX_OBJS = \
        libx/x11.o
index 2de051919ac0b1d33cb3ac6bffc651546e1f8cbd..21f93739fd39168494a89ccc46a0be0163f495fa 100644 (file)
@@ -50,6 +50,7 @@ typedef struct buf {
 typedef struct {
     size_t beg;
     size_t end;
+    size_t col;
 } Sel;
 
 void buf_load(Buf* buf, char* path);
@@ -136,20 +137,29 @@ typedef struct {
 } Row;
 
 typedef struct {
-    size_t nrows; /* number of rows in the view */
-    size_t ncols; /* number of columns in the view */
-    Row** rows;   /* array of row data structures */
-    Buf buffer;   /* the buffer used to populate the view */
+    //size_t posx;
+    //size_t posy;
+    //size_t height;
+    //size_t width;
+    size_t nrows;  /* number of rows in the view */
+    size_t ncols;  /* number of columns in the view */
+    Row** rows;    /* array of row data structures */
+    Buf buffer;    /* the buffer used to populate the view */
+    Sel selection; /* range of currently selected text */
 } View;
 
-void view_update(View* view, unsigned crsr, unsigned* csrx, unsigned* csry);
-size_t view_getoff(View* view, unsigned pos, unsigned row, unsigned col);
-void view_setsize(View* view, unsigned nrows, unsigned ncols);
-void view_getsize(View* view, unsigned* nrows, unsigned* ncols);
-Row* view_getrow(View* view, unsigned row);
-void view_clearrow(View* view, unsigned row);
-size_t view_setcell(View* view, unsigned row, unsigned col, uint32_t attr, Rune r);
-UGlyph* view_getglyph(View* view, unsigned row, unsigned col, unsigned* scrwidth);
+void view_init(View* view, char* file);
+void view_resize(View* view, size_t nrows, size_t ncols);
+void view_update(View* view, size_t* csrx, size_t* csry);
+Row* view_getrow(View* view, size_t row);
+void view_byrune(View* view, int move);
+void view_byline(View* view, int move);
+
+//size_t view_getoff(View* view, size_t pos, size_t row, size_t col);
+//void view_getsize(View* view, size_t* nrows, size_t* ncols);
+//void view_clearrow(View* view, size_t row);
+//size_t view_setcell(View* view, size_t row, size_t col, uint32_t attr, Rune r);
+//UGlyph* view_getglyph(View* view, size_t row, size_t col, size_t* scrwidth);
 
 void screen_update(Buf* buf, unsigned crsr, unsigned* csrx, unsigned* csry);
 unsigned screen_getoff(Buf* buf, unsigned pos, unsigned row, unsigned col);
@@ -175,11 +185,6 @@ void terminate(Process* proc, int sig);
 char* cmdread(char** cmd);
 void cmdwrite(char** cmd, char* text);
 
-/* Clipboard Access
- *****************************************************************************/
-void clipcopy(char* text);
-char* clippaste(void);
-
 /* Color Scheme Handling
  *****************************************************************************/
 /* color indexes for the colorscheme */
@@ -248,3 +253,4 @@ enum {
         0xff2aa198,   \
         0xff859900    \
     }
+#define DEFAULT_TAGS "Quit Save"
similarity index 80%
rename from inc/X.h
rename to inc/x11.h
index 8a492955997fc303eabf7b2ed9f094e5014dbfe8..6926efe71a1d25a6336eacd91cc13a29ed18fb88 100644 (file)
--- a/inc/X.h
+++ b/inc/x11.h
@@ -1,5 +1,3 @@
-#include <X11/Xft/Xft.h>
-
 typedef enum {
     MOUSE_ACT_UP,
     MOUSE_ACT_DOWN,
@@ -22,32 +20,20 @@ typedef struct {
     uint32_t palette[16];
 } XConfig;
 
-#ifndef MAXFONTS
-#define MAXFONTS 16
-#endif
-
-typedef struct {
-    struct {
-        int height;
-        int width;
-        int ascent;
-        int descent;
-        XftFont* match;
-        FcFontSet* set;
-        FcPattern* pattern;
-    } base;
-    struct {
-        XftFont* font;
-        uint32_t unicodep;
-    } cache[MAXFONTS];
-    int ncached;
-} XFont;
+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
@@ -126,11 +112,14 @@ void x11_window(char* name, int width, int height);
 void x11_dialog(char* name, int height, int width);
 void x11_show(void);
 void x11_loop(void);
+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_draw_rect(int color, int x, int y, int width, int height);
-void x11_draw_glyphs(int fg, int bg, XftGlyphFontSpec* glyphs, size_t nglyphs);
 void x11_getsize(int* width, int* height);
 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);
+void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str);
+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_glyphs(int fg, int bg, XGlyphSpec* glyphs, size_t nglyphs);
diff --git a/libedit/clip.c b/libedit/clip.c
deleted file mode 100644 (file)
index f1b0644..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdc.h>
-#include <utf.h>
-#include <edit.h>
-#include <unistd.h>
-
-#ifdef __MACH__
-char* CopyCmd[]  = { "pbcopy", NULL };
-char* PasteCmd[] = { "pbpaste", NULL };
-#else
-char* CopyCmd[]  = { "xsel", "-bi", NULL };
-char* PasteCmd[] = { "xsel", "-bo", NULL };
-#endif
-
-void clipcopy(char* text) {
-    cmdwrite(CopyCmd, text);
-}
-
-char* clippaste(void) {
-    return cmdread(PasteCmd);
-}
diff --git a/libedit/view.c b/libedit/view.c
new file mode 100644 (file)
index 0000000..570ced1
--- /dev/null
@@ -0,0 +1,160 @@
+#include <stdc.h>
+#include <utf.h>
+#include <edit.h>
+
+#define ATTR_NORMAL   (CLR_BASE03 << 8 | CLR_BASE0)
+#define ATTR_SELECTED (CLR_BASE0  << 8 | CLR_BASE03)
+
+static void clearrow(View* view, size_t row) {
+    Row* scrrow = view_getrow(view, row);
+    if (!scrrow) return;
+    for (size_t i = 0; i < view->ncols; i++)
+        scrrow->cols[i].rune = (Rune)' ';
+    scrrow->rlen = 0;
+    scrrow->len  = 0;
+}
+
+static size_t setcell(View* view, size_t row, size_t col, uint32_t attr, Rune r) {
+    if (row >= view->nrows || col >= view->ncols) return 0;
+    Row* scrrow = view_getrow(view, row);
+    int ncols = runewidth(col, r);
+    /* write the rune to the screen buf */
+    scrrow->cols[col].attr = attr;
+    if (r == '\t' || r == '\n' || r == RUNE_CRLF)
+        scrrow->cols[col].rune = ' ';
+    else
+        scrrow->cols[col].rune = r;
+    /* Update lengths */
+    scrrow->rlen += 1;
+    for (int i = 1; i < ncols; i++) {
+        scrrow->cols[col].attr = attr;
+        scrrow->cols[col+i].rune = '\0';
+    }
+    if ((col + ncols) > scrrow->len)
+        scrrow->len = col + ncols;
+    return ncols;
+}
+
+static bool selected(View* view, size_t pos) {
+    Sel sel = view->selection;
+    if (sel.end < sel.beg) {
+        size_t temp = sel.beg;
+        sel.beg = sel.end;
+        sel.end = temp;
+    }
+    return (sel.beg <= pos && pos < sel.end);
+}
+
+static size_t fill_row(View* view, unsigned row, size_t pos) {
+    view_getrow(view, row)->off = pos;
+    clearrow(view, row);
+    for (size_t x = 0; x < view->ncols;) {
+        uint32_t attr = (selected(view, pos) ? ATTR_SELECTED : ATTR_NORMAL);
+        Rune r = buf_get(&(view->buffer), pos++);
+        x += setcell(view, row, x, attr, r);
+        if (buf_iseol(&(view->buffer), pos-1)) break;
+    }
+    return pos;
+}
+
+static void reflow(View* view) {
+    size_t pos = view->rows[0]->off;
+    for (size_t y = 0; y < view->nrows; y++)
+        pos = fill_row(view, y, pos);
+}
+
+void view_init(View* view, char* file) {
+    memset(view, 0, sizeof(View));
+    buf_init(&(view->buffer));
+    if (file)
+        buf_load(&(view->buffer), file);
+}
+
+void view_resize(View* view, size_t nrows, size_t ncols) {
+    if (view->nrows == nrows && view->ncols == ncols)  return;
+    /* free the old row data */
+    if (view->nrows) {
+        for (unsigned i = 0; i < view->nrows; i++)
+            free(view->rows[i]);
+        free(view->rows);
+    }
+    /* create the new row data */
+    view->rows = calloc(nrows, sizeof(Row*));
+    for (unsigned i = 0; i < nrows; i++)
+        view->rows[i] = calloc(1, sizeof(Row) + (ncols * sizeof(UGlyph)));
+    /* update dimensions */
+    view->nrows = nrows;
+    view->ncols = ncols;
+    /* populate the screen buffer */
+    reflow(view);
+}
+
+void view_update(View* view, size_t* csrx, size_t* csry) {
+    size_t csr = view->selection.beg;
+    /* scroll the view and reflow the screen lines */
+    //sync_view(buf, csr);
+    reflow(view);
+    /* find the cursor on the new screen */
+    for (size_t y = 0; y < view->nrows; y++) {
+        size_t start = view->rows[y]->off;
+        size_t end   = view->rows[y]->off + view->rows[y]->rlen - 1;
+        if (start <= csr && csr <= end) {
+            size_t pos = start;
+            for (size_t x = 0; x < view->ncols;) {
+                if (pos == csr) {
+                    *csry = y, *csrx = x;
+                    break;
+                }
+                x += runewidth(x, buf_get(&(view->buffer),pos++));
+            }
+            break;
+        }
+    }
+}
+
+Row* view_getrow(View* view, size_t row) {
+    return (row < view->nrows ? view->rows[row] : NULL);
+}
+
+void view_byrune(View* view, int move) {
+    Sel sel = view->selection;
+    sel.beg = sel.end = buf_byrune(&(view->buffer), sel.end, move);
+    sel.col = buf_getcol(&(view->buffer), sel.end);
+    view->selection = sel;
+}
+
+void view_byline(View* view, int move) {
+    Sel sel = view->selection;
+    sel.beg = sel.end = buf_byline(&(view->buffer), sel.end, move);
+    sel.beg = sel.end = buf_setcol(&(view->buffer), sel.end, sel.col);
+    view->selection = sel;
+}
+
+
+//void view_update(View* view, size_t crsr, size_t* csrx, size_t* csry) {
+//
+//}
+//
+//size_t view_getoff(View* view, size_t pos, size_t row, size_t col) {
+//    return 0;
+//}
+//
+//void view_setsize(View* view, size_t nrows, size_t ncols) {
+//
+//}
+//
+//void view_getsize(View* view, size_t* nrows, size_t* ncols) {
+//
+//}
+//
+//void view_clearrow(View* view, size_t row) {
+//
+//}
+//
+//size_t view_setcell(View* view, size_t row, size_t col, uint32_t attr, Rune r) {
+//    return 0;
+//}
+//
+//UGlyph* view_getglyph(View* view, size_t row, size_t col, size_t* scrwidth) {
+//    return NULL;
+//}
index 8570bd350d94f5fb900d07040691057def6a977e..3739f999a245914c00afc35c3372a8d5b4effd77 100644 (file)
@@ -1,10 +1,32 @@
-#include <stdc.h>
-#include <X.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
+#include <X11/Xft/Xft.h>
+#include <x11.h>
+#include <stdc.h>
 #include <utf.h>
 #include <locale.h>
 
+#ifndef MAXFONTS
+#define MAXFONTS 16
+#endif
+
+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[MAXFONTS];
+    int ncached;
+};
+
 static bool Running = true;
 static struct {
     Window root;
@@ -215,19 +237,8 @@ void x11_loop(void) {
     XCloseDisplay(X.display);
 }
 
-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_getsize(int* width, int* height) {
-    *width  = X.width;
-    *height = X.height;
-}
-
-void x11_font_load(XFont* font, char* name) {
+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");
@@ -255,9 +266,33 @@ void x11_font_load(XFont* font, char* name) {
     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* font, XftGlyphFontSpec* spec, uint32_t rune) {
+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) {
@@ -302,25 +337,8 @@ void x11_font_getglyph(XFont* font, XftGlyphFontSpec* spec, uint32_t rune) {
     FcCharSetDestroy(fccharset);
 }
 
-void x11_draw_glyphs(int fg, int bg, XftGlyphFontSpec* 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);
-        xftcolor(&bgc, Config->palette[bg]);
-        x11_draw_rect(bg, specs[0].x, specs[0].y - h, nspecs * w, font->height);
-        XftColorFree(X.display, X.visual, X.colormap, &bgc);
-    }
-    xftcolor(&fgc, Config->palette[fg]);
-    XftDrawGlyphFontSpec(X.xft, &fgc, specs, nspecs);
-    XftColorFree(X.display, X.visual, X.colormap, &fgc);
-}
-
-size_t x11_font_getglyphs(XftGlyphFontSpec* specs, const XGlyph* glyphs, int len, XFont* font, int x, int y) {
+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 * font->base.width, winy = y * font->base.ascent;
     size_t numspecs = 0;
     for (int i = 0, xp = winx, yp = winy + font->base.ascent; i < len;) {
@@ -337,20 +355,38 @@ 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++;
+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);
+        xftcolor(&bgc, Config->palette[bg]);
+        x11_draw_rect(bg, specs[0].x, specs[0].y - h, nspecs * w, font->height);
+        XftColorFree(X.display, X.visual, X.colormap, &bgc);
     }
-    x11_draw_glyphs(fg, bg, specs, nspecs);
+    xftcolor(&fgc, Config->palette[fg]);
+    XftDrawGlyphFontSpec(X.xft, &fgc, (XftGlyphFontSpec*)specs, nspecs);
+    XftColorFree(X.display, X.visual, X.colormap, &fgc);
 }
 
-void x11_warp_mouse(int x, int y) {
-    XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y);
-}
+//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/xedit.c b/xedit.c
index df6c528f8c7f8185d5cda15ce201ed81c566f093..8b9d3091919db3b3c866868f93d8c13d2ef17b8a 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -1,5 +1,5 @@
 #include <stdc.h>
-#include <X.h>
+#include <x11.h>
 #include <utf.h>
 #include <edit.h>
 #include <ctype.h>
@@ -10,15 +10,20 @@ static void key_handler(Rune key);
 
 /* Global Data
  *****************************************************************************/
-Buf Buffer;
-Buf TagBuffer;
-unsigned TargetCol = 0;
-unsigned SelBeg = 0;
-unsigned SelEnd = 0;
-static unsigned ScrRows = 0;
-static unsigned ScrCols = 0;
+//Buf Buffer;
+//Buf TagBuffer;
+//unsigned TargetCol = 0;
+//unsigned SelBeg = 0;
+//unsigned SelEnd = 0;
+//static unsigned ScrRows = 0;
+//static unsigned ScrCols = 0;
+//static XFont Fonts;
+
 static bool TagWinExpanded = false;
-static XFont Fonts;
+static View TagView;
+static View BufView;
+static View* Focused = &BufView;
+static XFont Font;
 static XConfig Config = {
     .redraw       = redraw,
     .handle_key   = key_handler,
@@ -26,10 +31,210 @@ static XConfig Config = {
     .palette      = COLOR_PALETTE
 };
 
-/* new view globals */
-static View TagView;
-static View EditView;
-static View* Active = &EditView;
+/* UI Callbacks
+ *****************************************************************************/
+static void cursor_up(void) {
+    view_byline(Focused, -1);
+}
+
+static void cursor_dn(void) {
+    view_byline(Focused, +1);
+}
+
+static void cursor_left(void) {
+    view_byrune(Focused, -1);
+}
+
+static void cursor_right(void) {
+    view_byrune(Focused, +1);
+}
+
+/* UI Callbacks
+ *****************************************************************************/
+static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) {
+
+}
+
+/* Keyboard Bindings
+ *****************************************************************************/
+typedef struct {
+    Rune key;
+    void (*action)(void);
+} KeyBinding_T;
+
+static KeyBinding_T Insert[] = {
+    { KEY_UP,        cursor_up     },
+    { KEY_DOWN,      cursor_dn     },
+    { KEY_LEFT,      cursor_left   },
+    { KEY_RIGHT,     cursor_right  },
+    //{ KEY_CTRL_Q,    quit          },
+    //{ KEY_CTRL_S,    write         },
+    //{ KEY_CTRL_T,    tagwin        },
+    //{ KEY_CTRL_Z,    undo          },
+    //{ KEY_CTRL_Y,    redo          },
+    //{ KEY_CTRL_X,    cut           },
+    //{ KEY_CTRL_C,    copy          },
+    //{ KEY_CTRL_V,    paste         },
+    //{ KEY_HOME,      cursor_bol    },
+    //{ KEY_END,       cursor_eol    },
+    //{ KEY_DELETE,    delete        },
+    //{ KEY_BACKSPACE, backspace     },
+    { 0,             NULL          }
+};
+
+static void process_table(KeyBinding_T* bindings, Rune key) {
+    while (bindings->key) {
+        if (key == bindings->key) {
+            bindings->action();
+            return;
+        }
+        bindings++;
+    }
+    /* skip control and nonprintable characters */
+    if ((!isspace(key) && key < 0x20) ||
+        (key >= 0xE000 && key <= 0xF8FF))
+        return;
+    /* fallback to just inserting the rune */
+    //buf_ins(&Buffer, SelEnd++, key);
+    //SelBeg = SelEnd;
+    //TargetCol = buf_getcol(&Buffer, SelEnd);
+}
+
+static void key_handler(Rune key) {
+    /* ignore invalid keys */
+    if (key == RUNE_ERR) return;
+    /* handle the proper line endings */
+    if (key == '\r') key = '\n';
+    if (key == '\n' && Focused->buffer.crlf) key = RUNE_CRLF;
+    /* handle the key */
+    process_table(Insert, key);
+}
+
+/* Redisplay Functions
+ *****************************************************************************/
+static void draw_runes(unsigned x, unsigned y, int fg, int bg, UGlyph* glyphs, size_t rlen) {
+    XGlyphSpec specs[rlen];
+    while (rlen) {
+        size_t nspecs = x11_font_getglyphs(specs, (XGlyph*)glyphs, rlen, Font, x, y);
+        x11_draw_glyphs(fg, bg, specs, nspecs);
+        rlen -= nspecs;
+    }
+}
+
+static void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) {
+    XGlyphSpec specs[rlen];
+    size_t i = 0;
+    while (rlen) {
+        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 void draw_status(int fg, unsigned ncols) {
+    UGlyph glyphs[ncols], *status = glyphs;
+    (status++)->rune = (BufView.buffer.charset == BINARY ? 'B' : 'U');
+    (status++)->rune = (BufView.buffer.crlf ? 'C' : 'N');
+    (status++)->rune = (BufView.buffer.modified ? '*' : ' ');
+    (status++)->rune = ' ';
+    char* path = (BufView.buffer.path ? BufView.buffer.path : "*scratch*");
+    size_t len = strlen(path);
+    if (len > ncols-4) {
+        (status++)->rune = '.';
+        (status++)->rune = '.';
+        (status++)->rune = '.';
+        path += (len - ncols) + 6;
+    }
+    while(*path)
+        (status++)->rune = *path++;
+    draw_runes(0, 0, fg, 0, glyphs, status - glyphs);
+}
+
+static size_t stackvert(size_t off, size_t rows) {
+    return (off + 4 + (rows * x11_font_height(Font)));
+}
+
+static size_t draw_view(size_t off, View* view, size_t rows, size_t width) {
+    size_t fheight = x11_font_height(Font);
+    size_t fwidth  = x11_font_width(Font);
+    size_t cols    = (width - 4) / fwidth;
+    view_resize(view, rows, cols);
+    /* update the screen buffer and retrieve cursor coordinates */
+    size_t csrx, csry;
+    view_update(view, &csrx, &csry);
+    /* flush the screen buffer */
+    for (size_t y = 0; y < rows; y++) {
+        Row* row = view_getrow(view, y);
+        draw_glyphs(2, off + ((y+1) * fheight), row->cols, row->rlen, row->len);
+    }
+    /* Place cursor on screen */
+    x11_draw_rect(CLR_BASE3, 2 + csrx * fwidth, off + (csry * fheight), 1, fheight);
+    return (off + 4 + (rows * x11_font_height(Font)));
+}
+
+static void redraw(int width, int height) {
+    size_t vmargin = 2;
+    size_t hmargin = 2;
+    size_t fheight = x11_font_height(Font);
+    size_t fwidth  = x11_font_width(Font);
+    /* clear background and draw status */
+    size_t vpos = 0;
+    x11_draw_rect(CLR_BASE03, 0, vpos, width, height);
+    draw_status(CLR_BASE3, width / fwidth);
+    /* draw the tag buffer */
+    vpos = stackvert(vpos, 1);
+    x11_draw_rect(CLR_BASE01, 0, vpos++, width, 1);
+    size_t totrows = (height - vpos - 9) / fheight;
+    size_t tagrows = (TagWinExpanded ? (totrows / 4) : 1);
+    size_t bufrows = totrows - tagrows;
+    vpos = draw_view(3+vpos, &TagView, tagrows, width);
+    /* draw thee dit buffer */
+    x11_draw_rect(CLR_BASE01, 0, ++vpos, width, 1);
+    vpos = draw_view(3+vpos, &BufView, bufrows, width);
+}
+
+/* Main Routine
+ *****************************************************************************/
+int main(int argc, char** argv) {
+    /* load the buffer views */
+    view_init(&TagView, NULL);
+    view_init(&BufView, (argc > 1 ? argv[1] : NULL));
+    buf_putstr(&(TagView.buffer), 0, 0, DEFAULT_TAGS);
+    /* initialize the display engine */
+    x11_init(&Config);
+    x11_window("edit", Width, Height);
+    x11_show();
+    Font = x11_font_load(FONTNAME);
+    x11_loop();
+    return 0;
+}
+
+#if 0
+#if 0
+/* External Commands
+ *****************************************************************************/
+#ifdef __MACH__
+static char* CopyCmd[]  = { "pbcopy", NULL };
+static char* PasteCmd[] = { "pbpaste", NULL };
+#else
+static char* CopyCmd[]  = { "xsel", "-bi", NULL };
+static char* PasteCmd[] = { "xsel", "-bo", NULL };
+#endif
 
 /* Keyboard Actions
  *****************************************************************************/
@@ -75,43 +280,23 @@ static void redo(void) {
 
 static void cut(void) {
     char* str = buf_getstr(&Buffer, SelBeg, SelEnd);
-    clipcopy(str);
+    cmdwrite(CopyCmd, str);
     free(str);
     delete();
 }
 
 static void copy(void) {
     char* str = buf_getstr(&Buffer, SelBeg, SelEnd);
-    clipcopy(str);
+    cmdwrite(CopyCmd, str);
     free(str);
 }
 
 static void paste(void) {
-    char* str = clippaste();
+    char* str = cmdread(PasteCmd);
     buf_putstr(&Buffer, SelBeg, SelEnd, str);
     free(str);
 }
 
-static void cursor_up(void) {
-    SelBeg = SelEnd = buf_byline(&Buffer, SelEnd, -1);
-    SelBeg = SelEnd = buf_setcol(&Buffer, SelEnd, TargetCol);
-}
-
-static void cursor_dn(void) {
-    SelBeg = SelEnd = buf_byline(&Buffer, SelEnd, 1);
-    SelBeg = SelEnd = buf_setcol(&Buffer, SelEnd, TargetCol);
-}
-
-static void cursor_left(void) {
-    SelBeg = SelEnd = buf_byrune(&Buffer, SelEnd, -1);
-    TargetCol = buf_getcol(&Buffer, SelEnd);
-}
-
-static void cursor_right(void) {
-    SelBeg = SelEnd = buf_byrune(&Buffer, SelEnd, 1);
-    TargetCol = buf_getcol(&Buffer, SelEnd);
-}
-
 static void cursor_bol(void) {
     SelBeg = SelEnd = buf_bol(&Buffer, SelEnd);
     TargetCol = 0;
@@ -126,69 +311,17 @@ static void tagwin(void) {
     TagWinExpanded = !TagWinExpanded;
 }
 
-/* Keyboard Bindings
- *****************************************************************************/
-typedef struct {
-    Rune key;
-    void (*action)(void);
-} KeyBinding_T;
-
-static KeyBinding_T Insert[] = {
-    { KEY_CTRL_Q,    quit          },
-    { KEY_CTRL_S,    write         },
-    { KEY_CTRL_T,    tagwin        },
-    { KEY_CTRL_Z,    undo          },
-    { KEY_CTRL_Y,    redo          },
-    { KEY_CTRL_X,    cut           },
-    { KEY_CTRL_C,    copy          },
-    { KEY_CTRL_V,    paste         },
-    { KEY_UP,        cursor_up     },
-    { KEY_DOWN,      cursor_dn     },
-    { KEY_LEFT,      cursor_left   },
-    { KEY_RIGHT,     cursor_right  },
-    { KEY_HOME,      cursor_bol    },
-    { KEY_END,       cursor_eol    },
-    { KEY_DELETE,    delete        },
-    { KEY_BACKSPACE, backspace     },
-    { 0,             NULL          }
-};
-
-static void process_table(KeyBinding_T* bindings, Rune key) {
-    while (bindings->key) {
-        if (key == bindings->key) {
-            bindings->action();
-            return;
-        }
-        bindings++;
-    }
-    /* skip control and nonprintable characters */
-    if ((!isspace(key) && key < 0x20) ||
-        (key >= 0xE000 && key <= 0xF8FF))
-        return;
-    /* fallback to just inserting the rune */
-    buf_ins(&Buffer, SelEnd++, key);
-    SelBeg = SelEnd;
-    TargetCol = buf_getcol(&Buffer, SelEnd);
-}
-
-static void key_handler(Rune key) {
-    /* ignore invalid keys */
-    if (key == RUNE_ERR) return;
-    /* handle the proper line endings */
-    if (key == '\r') key = '\n';
-    if (key == '\n' && Buffer.crlf) key = RUNE_CRLF;
-    /* handle the key */
-    process_table(Insert, key);
-}
+#endif
 
 /* Mouse Actions
  *****************************************************************************/
+#if 0
 void unused(int x, int y) {
 }
 
 void move_cursor(int x, int y) {
     if (y == 0) return;
-    SelBeg = SelEnd = screen_getoff(&Buffer, SelEnd, y-1, x);
+    //SelBeg = SelEnd = screen_getoff(&Buffer, SelEnd, y-1, x);
     TargetCol = buf_getcol(&Buffer, SelEnd);
 }
 
@@ -223,18 +356,17 @@ void selection(int x, int y) {
 }
 
 void search(int x, int y) {
-    unsigned clickpos = screen_getoff(&Buffer, SelEnd, y-1, x);
-    if (clickpos < SelBeg || clickpos > SelEnd) {
-        move_cursor(x,y);
-        selection(x,y);
-    } else {
-        buf_find(&Buffer, &SelBeg, &SelEnd);
-    }
-    unsigned c, r;
-    screen_update(&Buffer, SelEnd, &c, &r);
-    extern void move_pointer(unsigned c, unsigned r);
-    move_pointer(c, r);
-
+    //unsigned clickpos = screen_getoff(&Buffer, SelEnd, y-1, x);
+    //if (clickpos < SelBeg || clickpos > SelEnd) {
+    //    move_cursor(x,y);
+    //    selection(x,y);
+    //} else {
+    //    buf_find(&Buffer, &SelBeg, &SelEnd);
+    //}
+    //unsigned c, r;
+    //screen_update(&Buffer, SelEnd, &c, &r);
+    //extern void move_pointer(unsigned c, unsigned r);
+    //move_pointer(c, r);
 }
 
 void scrollup(int x, int y) {
@@ -244,7 +376,7 @@ void scrollup(int x, int y) {
 void scrolldn(int x, int y) {
     SelBeg = SelEnd = buf_byline(&Buffer, SelEnd, ScrollLines);
 }
-
+#endif
 /* Mouse Input Handler
  *****************************************************************************/
 struct {
@@ -252,105 +384,52 @@ struct {
     uint32_t count;
 } Buttons[5] = { 0 };
 
-void (*Actions[5][3])(int x, int y) = {
+void (*Actions[5][3])(int x, int y) = { 0
                           /*  Single       Double     Triple    */
-    [MOUSE_BTN_LEFT]      = { move_cursor, selection, bigword,  },
-    [MOUSE_BTN_MIDDLE]    = { unused,      unused,    unused,   },
-    [MOUSE_BTN_RIGHT]     = { search,      search,    search,   },
-    [MOUSE_BTN_WHEELUP]   = { scrollup,    scrollup,  scrollup, },
-    [MOUSE_BTN_WHEELDOWN] = { scrolldn,    scrolldn,  scrolldn, },
+    //[MOUSE_BTN_LEFT]      = { move_cursor, selection, bigword,  },
+    //[MOUSE_BTN_MIDDLE]    = { unused,      unused,    unused,   },
+    //[MOUSE_BTN_RIGHT]     = { search,      search,    search,   },
+    //[MOUSE_BTN_WHEELUP]   = { scrollup,    scrollup,  scrollup, },
+    //[MOUSE_BTN_WHEELDOWN] = { scrolldn,    scrolldn,  scrolldn, },
 };
 
 static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) {
-    unsigned row  = y / Fonts.base.height;
-    unsigned col  = x / Fonts.base.width;
-    unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1);
-
-    //if (row == 0) {
-    //    puts("status");
-    //} else if (row >= 1 && row <= twsz) {
-    //    puts("tagwin");
-    //} else {
-    //    puts("editwin");
+    //unsigned row  = y / Fonts.base.height;
+    //unsigned col  = x / Fonts.base.width;
+    //unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1);
+
+    ////if (row == 0) {
+    ////    puts("status");
+    ////} else if (row >= 1 && row <= twsz) {
+    ////    puts("tagwin");
+    ////} else {
+    ////    puts("editwin");
+    ////}
+
+    //if (act == MOUSE_ACT_DOWN) {
+    //    //if (mevnt->button >= 5) return;
+    //    ///* update the number of clicks */
+    //    //uint32_t now = getmillis();
+    //    //uint32_t elapsed = now - Buttons[mevnt->button].time;
+    //    //if (elapsed <= 250)
+    //    //    Buttons[mevnt->button].count++;
+    //    //else
+    //    //    Buttons[mevnt->button].count = 1;
+    //    //Buttons[mevnt->button].time = now;
+    //    ///* execute the click action */
+    //    //uint32_t nclicks = Buttons[mevnt->button].count;
+    //    //nclicks = (nclicks > 3 ? 1 : nclicks);
+    //    //Actions[mevnt->button][nclicks-1](mevnt);
+    //} else if (act == MOUSE_ACT_MOVE) {
+    //    puts("move");
+    //    //if (mevnt->y == 0 || mevnt->button != MOUSE_LEFT) return;
+    //    //SelEnd = screen_getoff(&Buffer, SelEnd, mevnt->y-1, mevnt->x);
+    //    //TargetCol = buf_getcol(&Buffer, SelEnd);
     //}
-
-    if (act == MOUSE_ACT_DOWN) {
-        //if (mevnt->button >= 5) return;
-        ///* update the number of clicks */
-        //uint32_t now = getmillis();
-        //uint32_t elapsed = now - Buttons[mevnt->button].time;
-        //if (elapsed <= 250)
-        //    Buttons[mevnt->button].count++;
-        //else
-        //    Buttons[mevnt->button].count = 1;
-        //Buttons[mevnt->button].time = now;
-        ///* execute the click action */
-        //uint32_t nclicks = Buttons[mevnt->button].count;
-        //nclicks = (nclicks > 3 ? 1 : nclicks);
-        //Actions[mevnt->button][nclicks-1](mevnt);
-    } else if (act == MOUSE_ACT_MOVE) {
-        //if (mevnt->y == 0 || mevnt->button != MOUSE_LEFT) return;
-        //SelEnd = screen_getoff(&Buffer, SelEnd, mevnt->y-1, mevnt->x);
-        //TargetCol = buf_getcol(&Buffer, SelEnd);
-    }
 }
 
-
 /* Screen Redraw
  *****************************************************************************/
-static void draw_runes(unsigned x, unsigned y, int fg, int bg, UGlyph* glyphs, size_t rlen) {
-    XftGlyphFontSpec specs[rlen];
-    while (rlen) {
-        size_t nspecs = x11_font_getglyphs(specs, (XGlyph*)glyphs, rlen, &Fonts, x, y);
-        x11_draw_glyphs(fg, bg, specs, nspecs);
-        rlen -= nspecs;
-    }
-}
-
-static void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) {
-    XftGlyphFontSpec specs[rlen];
-    size_t i = 0;
-    while (rlen) {
-        int numspecs = 0;
-        uint32_t attr = glyphs[i].attr;
-        while (i < ncols && glyphs[i].attr == attr) {
-            x11_font_getglyph(&Fonts, &(specs[numspecs]), glyphs[i].rune);
-            specs[numspecs].x = x;
-            specs[numspecs].y = y - Fonts.base.descent;
-            x += Fonts.base.width;
-            numspecs++;
-            i++;
-            /* skip over null chars which mark multi column runes */
-            for (; i < ncols && !glyphs[i].rune; i++)
-                x += Fonts.base.width;
-        }
-        /* 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 void draw_status(int fg, unsigned ncols) {
-    UGlyph glyphs[ncols], *status = glyphs;
-    (status++)->rune = (Buffer.charset == BINARY ? 'B' : 'U');
-    (status++)->rune = (Buffer.crlf ? 'C' : 'N');
-    (status++)->rune = (Buffer.modified ? '*' : ' ');
-    (status++)->rune = ' ';
-    char* path = (Buffer.path ? Buffer.path : "*scratch*");
-    size_t len = strlen(path);
-    if (len > ncols-4) {
-        (status++)->rune = '.';
-        (status++)->rune = '.';
-        (status++)->rune = '.';
-        path += (len - ncols) + 6;
-    }
-    while(*path)
-        (status++)->rune = *path++;
-    draw_runes(0, 0, fg, 0, glyphs, status - glyphs);
-}
-
 
 static void draw_tagwin(unsigned off, unsigned rows, unsigned cols) {
     //screen_setsize(&TagBuffer, rows, cols);
@@ -358,45 +437,44 @@ static void draw_tagwin(unsigned off, unsigned rows, unsigned cols) {
 }
 
 static void draw_bufwin(unsigned off, unsigned rows, unsigned cols) {
-    screen_setsize(&Buffer, rows, cols);
-    /* update the screen buffer and retrieve cursor coordinates */
-    unsigned csrx, csry;
-    screen_update(&Buffer, SelEnd, &csrx, &csry);
-    /* flush the screen buffer */
-    unsigned nrows, ncols;
-    screen_getsize(&nrows, &ncols);
-    draw_status(CLR_BASE2, ncols);
-    for (unsigned y = 0; y < nrows; y++) {
-        Row* row = screen_getrow(y);
-        draw_glyphs(0, off + ((y+1) * Fonts.base.height), row->cols, row->rlen, row->len);
-    }
-    /* Place cursor on screen */
-    x11_draw_rect(CLR_BASE3, csrx * Fonts.base.width, off + (csry * Fonts.base.height), 1, Fonts.base.height);
+    //screen_setsize(&Buffer, rows, cols);
+    ///* update the screen buffer and retrieve cursor coordinates */
+    //unsigned csrx, csry;
+    //screen_update(&Buffer, SelEnd, &csrx, &csry);
+    ///* flush the screen buffer */
+    //unsigned nrows, ncols;
+    //screen_getsize(&nrows, &ncols);
+    //draw_status(CLR_BASE2, ncols);
+    //for (unsigned y = 0; y < nrows; y++) {
+    //    Row* row = screen_getrow(y);
+    //    draw_glyphs(0, off + ((y+1) * Fonts.base.height), row->cols, row->rlen, row->len);
+    //}
+    ///* Place cursor on screen */
+    //x11_draw_rect(CLR_BASE3, csrx * Fonts.base.width, off + (csry * Fonts.base.height), 1, Fonts.base.height);
 }
 
 static void redraw(int width, int height) {
-    unsigned fheight = Fonts.base.height;
-    unsigned fwidth  = Fonts.base.width;
-    ScrRows = height / Fonts.base.height;
-    ScrCols = width  / Fonts.base.width;
-    /* clear background and draw status */
-    x11_draw_rect(CLR_BASE03, 0, 0, width, height);
-    draw_status(CLR_BASE2, ScrCols);
-    /* draw the tag window */
-    unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1);
-    x11_draw_rect(CLR_BASE02, 0, fheight, width, twsz * fheight);
-    x11_draw_rect(CLR_BASE01, 0, fheight, width, 1);
-    draw_tagwin(fheight, twsz, ScrCols);
-    /* draw the file window */
-    x11_draw_rect(CLR_BASE01, 0, (twsz+1) * fheight, width, 1);
-    draw_bufwin((twsz+1) * fheight, ScrRows - (twsz), ScrCols);
+    //unsigned fheight = Fonts.base.height;
+    //unsigned fwidth  = Fonts.base.width;
+    //ScrRows = height / Fonts.base.height;
+    //ScrCols = width  / Fonts.base.width;
+    ///* clear background and draw status */
+    //x11_draw_rect(CLR_BASE03, 0, 0, width, height);
+    //draw_status(CLR_BASE2, ScrCols);
+    ///* draw the tag window */
+    //unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1);
+    //x11_draw_rect(CLR_BASE02, 0, fheight, width, twsz * fheight);
+    //x11_draw_rect(CLR_BASE01, 0, fheight, width, 1);
+    //draw_tagwin(fheight, twsz, ScrCols);
+    ///* draw the file window */
+    //x11_draw_rect(CLR_BASE01, 0, (twsz+1) * fheight, width, 1);
+    //draw_bufwin((twsz+1) * fheight, ScrRows - (twsz), ScrCols);
 }
 
 int main(int argc, char** argv) {
-    /* load the buffer */
-    buf_init(&Buffer);
-    if (argc > 1)
-        buf_load(&Buffer, argv[1]);
+    /* load the buffer views */
+    view_init(&TagView, NULL);
+    view_init(&BufView, (argc > 1 ? argv[1] : NULL));
     /* initialize the display engine */
     x11_init(&Config);
     x11_window("edit", Width, Height);
@@ -411,3 +489,4 @@ void move_pointer(unsigned x, unsigned y) {
     y = ((y+1) * Fonts.base.height) + (Fonts.base.height / 2);
     x11_warp_mouse(x,y);
 }
+#endif
diff --git a/xpick.c b/xpick.c
index ac36baf4e5708c87563ecdc6577e7b7563361fc2..72e586666f03fa20c26b3d5e6bdf25338e628a0a 100644 (file)
--- a/xpick.c
+++ b/xpick.c
@@ -1,5 +1,5 @@
 #include <stdc.h>
-#include <X.h>
+#include <x11.h>
 #include <utf.h>
 #include <edit.h>
 #include <vec.h>