]> git.mdlowis.com Git - projs/tide.git/commitdiff
fleshed out the mouse selection logic a bit more
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 22 Oct 2016 01:55:14 +0000 (21:55 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 22 Oct 2016 01:55:14 +0000 (21:55 -0400)
buf.c
edit.h
keyboard.c
mouse.c
utils.c
xedit.c

diff --git a/buf.c b/buf.c
index 75533a6425ff78cd8c34ec1610e57b324cbb6588..601fcccba99ee0d99951f27e90032ec1cf2f1665 100644 (file)
--- a/buf.c
+++ b/buf.c
@@ -137,6 +137,30 @@ unsigned buf_eol(Buf* buf, unsigned off) {
     return off;
 }
 
+unsigned buf_bow(Buf* buf, unsigned off)
+{
+    for (; isword(buf_get(buf, off-1)); off--);
+    return off;
+}
+
+unsigned buf_eow(Buf* buf, unsigned off)
+{
+    for (; isword(buf_get(buf, off)); off++);
+    return off-1;
+}
+
+unsigned buf_lscan(Buf* buf, unsigned off, Rune r)
+{
+    for (; r != buf_get(buf, off); off--);
+    return off;
+}
+
+unsigned buf_rscan(Buf* buf, unsigned off, Rune r)
+{
+    for (; r != buf_get(buf, off); off++);
+    return off;
+}
+
 unsigned buf_end(Buf* buf) {
     size_t bufsz = buf->bufend - buf->bufstart;
     size_t gapsz = buf->gapend - buf->gapstart;
diff --git a/edit.h b/edit.h
index 3d136a78491f549127bb9578566195ecb75ede39..1c59866756d8c2232a338dd217c80fca54f34d40 100644 (file)
--- a/edit.h
+++ b/edit.h
@@ -5,18 +5,6 @@
 #include <stdarg.h>
 #include <string.h>
 
-/* Utility Functions
- *****************************************************************************/
-typedef struct {
-    uint8_t* buf; /* memory mapped byte buffer */
-    size_t len;   /* length of the buffer */
-} FMap;
-
-FMap fmap(char* path);
-void funmap(FMap file);
-void die(const char* fmt, ...);
-uint32_t getmillis(void);
-
 /* Unicode Handling
  *****************************************************************************/
 enum {
@@ -37,6 +25,20 @@ Rune fgetrune(FILE* f);
 void fputrune(Rune rune, FILE* f);
 int runewidth(unsigned col, Rune r);
 
+/* Utility Functions
+ *****************************************************************************/
+typedef struct {
+    uint8_t* buf; /* memory mapped byte buffer */
+    size_t len;   /* length of the buffer */
+} FMap;
+
+FMap fmap(char* path);
+void funmap(FMap file);
+void die(const char* fmt, ...);
+uint32_t getmillis(void);
+bool isword(Rune r);
+
+
 /* Buffer management functions
  *****************************************************************************/
 typedef struct buf {
@@ -62,6 +64,12 @@ Rune buf_get(Buf* buf, unsigned pos);
 bool buf_iseol(Buf* buf, unsigned pos);
 unsigned buf_bol(Buf* buf, unsigned pos);
 unsigned buf_eol(Buf* buf, unsigned pos);
+
+unsigned buf_bow(Buf* buf, unsigned pos);
+unsigned buf_eow(Buf* buf, unsigned pos);
+unsigned buf_lscan(Buf* buf, unsigned pos, Rune r);
+unsigned buf_rscan(Buf* buf, unsigned pos, Rune r);
+
 unsigned buf_end(Buf* buf);
 unsigned buf_byrune(Buf* buf, unsigned pos, int count);
 unsigned buf_byline(Buf* buf, unsigned pos, int count);
@@ -241,7 +249,6 @@ enum ColorScheme {
 /* variable for holding the currently selected color scheme */
 extern enum ColorScheme ColorBase;
 extern Buf Buffer;
-extern unsigned CursorPos;
 extern unsigned TargetCol;
 extern unsigned DotBeg;
 extern unsigned DotEnd;
index 4189d51d4ed20b8cd217a9ed739fb225d42d8cdc..7220d74eabdaa7936b956b60f0a721fea73707f6 100644 (file)
@@ -5,51 +5,41 @@ static void toggle_colors(void) {
 }
 
 static void cursor_up(void) {
-    CursorPos = buf_byline(&Buffer, CursorPos, -1);
-    CursorPos = buf_setcol(&Buffer, CursorPos, TargetCol);
+    DotBeg = DotEnd = buf_byline(&Buffer, DotEnd, -1);
+    DotBeg = DotEnd = buf_setcol(&Buffer, DotEnd, TargetCol);
 }
 
 static void cursor_dn(void) {
-    CursorPos = buf_byline(&Buffer, CursorPos, 1);
-    CursorPos = buf_setcol(&Buffer, CursorPos, TargetCol);
+    DotBeg = DotEnd = buf_byline(&Buffer, DotEnd, 1);
+    DotBeg = DotEnd = buf_setcol(&Buffer, DotEnd, TargetCol);
 }
 
 static void cursor_left(void) {
-    CursorPos = buf_byrune(&Buffer, CursorPos, -1);
-    TargetCol = buf_getcol(&Buffer, CursorPos);
+    DotBeg = DotEnd = buf_byrune(&Buffer, DotEnd, -1);
+    TargetCol = buf_getcol(&Buffer, DotEnd);
 }
 
 static void cursor_right(void) {
-    CursorPos = buf_byrune(&Buffer, CursorPos, 1);
-    TargetCol = buf_getcol(&Buffer, CursorPos);
+    DotBeg = DotEnd = buf_byrune(&Buffer, DotEnd, 1);
+    TargetCol = buf_getcol(&Buffer, DotEnd);
 }
 
 static void cursor_bol(void) {
-    CursorPos = buf_bol(&Buffer, CursorPos);
+    DotBeg = DotEnd = buf_bol(&Buffer, DotEnd);
     TargetCol = 0;
 }
 
 static void cursor_eol(void) {
-    CursorPos = buf_eol(&Buffer, CursorPos);
+    DotBeg = DotEnd = buf_eol(&Buffer, DotEnd);
     TargetCol = (unsigned)-1;
 }
 
-static void backspace(void) {
-    if (CursorPos == 0) return;
-    buf_del(&Buffer, --CursorPos);
-    TargetCol = buf_getcol(&Buffer, CursorPos);
-}
-
-static void delete(void) {
-    buf_del(&Buffer, CursorPos);
-}
-
 static void insert_before(void) {
     Buffer.insert_mode = true;
 }
 
 static void insert_after(void) {
-    CursorPos++;
+    DotEnd++;
     Buffer.insert_mode = true;
 }
 
@@ -70,11 +60,30 @@ static void quit(void) {
     if (!Buffer.modified || num_clicks >= 2)
         exit(0);
 }
+static void dot_delete(void) {
+    if (DotEnd == buf_end(&Buffer)) return;
+    size_t n = DotEnd - DotBeg;
+    bool insert = Buffer.insert_mode;
+    if (!insert || !n) n++;
+    Buffer.insert_mode = true;
+    for (size_t i = 0; i < n; i++)
+        buf_del(&Buffer, DotBeg);
+    DotEnd = DotBeg;
+    TargetCol = buf_getcol(&Buffer, DotEnd);
+    Buffer.insert_mode = insert;
+}
+
+static void dot_backspace(void) {
+    if (DotBeg > 0 && DotBeg == DotEnd) DotBeg--;
+    while (DotBeg < DotEnd)
+        buf_del(&Buffer, --DotEnd);
+    TargetCol = buf_getcol(&Buffer, DotEnd);
+}
 
 static void insert(Rune r) {
     if (!Buffer.insert_mode) return;
-    buf_ins(&Buffer, CursorPos++, r);
-    TargetCol = buf_getcol(&Buffer, CursorPos);
+    buf_ins(&Buffer, DotEnd++, r);
+    TargetCol = buf_getcol(&Buffer, DotEnd);
 }
 
 /*****************************************************************************/
@@ -85,24 +94,26 @@ typedef struct {
 } KeyBinding_T;
 
 static KeyBinding_T Normal[] = {
-    { KEY_F6,    toggle_colors },
-    { KEY_UP,    cursor_up     },
-    { KEY_DOWN,  cursor_dn     },
-    { KEY_LEFT,  cursor_left   },
-    { KEY_RIGHT, cursor_right  },
-    { KEY_HOME,  cursor_bol    },
-    { KEY_END,   cursor_eol    },
-    { 'q',       quit          },
-    { 's',       write         },
-    { 'a',       insert_after  },
-    { 'i',       insert_before },
-    { 'k',       cursor_up     },
-    { 'j',       cursor_dn     },
-    { 'h',       cursor_left   },
-    { 'l',       cursor_right  },
-    { '0',       cursor_bol    },
-    { '$',       cursor_eol    },
-    { 0,         NULL          }
+    { KEY_F6,     toggle_colors },
+    { 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, dot_delete    },
+    { 'q',        quit          },
+    { 's',        write         },
+    { 'a',        insert_after  },
+    { 'i',        insert_before },
+    { 'k',        cursor_up     },
+    { 'j',        cursor_dn     },
+    { 'h',        cursor_left   },
+    { 'l',        cursor_right  },
+    { '0',        cursor_bol    },
+    { '$',        cursor_eol    },
+    { 'd',        dot_delete    },
+    { 0,          NULL          }
 };
 
 static KeyBinding_T Insert[] = {
@@ -114,8 +125,8 @@ static KeyBinding_T Insert[] = {
     { KEY_HOME,      cursor_bol    },
     { KEY_END,       cursor_eol    },
     { KEY_ESCAPE,    exit_insert   },
-    { KEY_DELETE,    delete        },
-    { KEY_BACKSPACE, backspace     },
+    { KEY_DELETE,    dot_delete    },
+    { KEY_BACKSPACE, dot_backspace },
     { 0,             NULL          }
 };
 
diff --git a/mouse.c b/mouse.c
index f6c602d2e9824ae88576332ea43b8ccf3ecf437b..87546e5c446cb3a87a7733e277d7864904a7cb7f 100644 (file)
--- a/mouse.c
+++ b/mouse.c
@@ -6,26 +6,47 @@ void unused(MouseEvent* mevnt) {
 
 void move_cursor(MouseEvent* mevnt) {
     if (mevnt->y == 0) return;
-    CursorPos = screen_getoff(&Buffer, CursorPos, mevnt->y-1, mevnt->x);
-    TargetCol = buf_getcol(&Buffer, CursorPos);
+    DotEnd = screen_getoff(&Buffer, DotEnd, mevnt->y-1, mevnt->x);
+    TargetCol = buf_getcol(&Buffer, DotEnd);
+    DotBeg = DotEnd;
 }
 
-void select_word(MouseEvent* mevnt) {
-    (void)mevnt;
-}
-
-void select_line(MouseEvent* mevnt) {
+void select(MouseEvent* mevnt) {
     (void)mevnt;
+    unsigned bol = buf_bol(&Buffer, DotEnd);
+    Rune r = buf_get(&Buffer, DotEnd);
+    if (DotEnd == bol || r == '\n' || r == RUNE_CRLF) {
+        DotBeg = bol;
+        DotEnd = buf_eol(&Buffer, DotEnd);
+    } else if (isword(r)) {
+        DotBeg = buf_bow(&Buffer, DotEnd);
+        DotEnd = buf_eow(&Buffer, DotEnd);
+        if (Buffer.insert_mode) DotEnd++;
+    } else if (r == '(' || r == ')') {
+        DotBeg = buf_lscan(&Buffer, DotEnd, '(');
+        DotEnd = buf_rscan(&Buffer, DotEnd, ')');
+        if (Buffer.insert_mode) DotEnd++;
+    } else if (r == '[' || r == ']') {
+        DotBeg = buf_lscan(&Buffer, DotEnd, '[');
+        DotEnd = buf_rscan(&Buffer, DotEnd, ']');
+        if (Buffer.insert_mode) DotEnd++;
+    } else if (r == '{' || r == '}') {
+        DotBeg = buf_lscan(&Buffer, DotEnd, '{');
+        DotEnd = buf_rscan(&Buffer, DotEnd, '}');
+        if (Buffer.insert_mode) DotEnd++;
+    } else {
+        /* scan for big word */
+    }
 }
 
 void scrollup(MouseEvent* mevnt) {
     (void)mevnt;
-    CursorPos = buf_byline(&Buffer, CursorPos, -ScrollLines);
+    DotBeg = DotEnd = buf_byline(&Buffer, DotEnd, -ScrollLines);
 }
 
 void scrolldn(MouseEvent* mevnt) {
     (void)mevnt;
-    CursorPos = buf_byline(&Buffer, CursorPos, ScrollLines);
+    DotBeg = DotEnd = buf_byline(&Buffer, DotEnd, ScrollLines);
 }
 
 /*****************************************************************************/
@@ -44,8 +65,8 @@ struct {
 void (*Actions[5][3])(MouseEvent* mevnt) = {
     [MOUSE_LEFT] = {
         [SINGLE_CLICK] = move_cursor,
-        [DOUBLE_CLICK] = select_word,
-        [TRIPLE_CLICK] = select_line,
+        [DOUBLE_CLICK] = select,
+        [TRIPLE_CLICK] = unused,
     },
     [MOUSE_MIDDLE] = {
         [SINGLE_CLICK] = unused,
@@ -86,7 +107,9 @@ static void handle_click(MouseEvent* mevnt) {
 }
 
 static void handle_drag(MouseEvent* mevnt) {
-    (void)mevnt;
+    if (mevnt->y == 0 || mevnt->button != MOUSE_LEFT) return;
+    DotEnd = screen_getoff(&Buffer, DotEnd, mevnt->y-1, mevnt->x);
+    TargetCol = buf_getcol(&Buffer, DotEnd);
 }
 
 void handle_mouse(MouseEvent* mevnt) {
diff --git a/utils.c b/utils.c
index 33e339256dd872d36b93f855a457ba054d4ef0ae..f8d6c13984ab0a0664f84905319fbc3f0a2b0b9f 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -7,6 +7,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <ctype.h>
 
 #ifdef __MACH__
 #define CLOCK_MONOTONIC 0
@@ -57,3 +58,8 @@ void funmap(FMap file) {
     if (file.buf)
         munmap(file.buf, file.len);
 }
+
+bool isword(Rune r) {
+    return (r < 127 && (isalnum(r) || r == '_'));
+}
+
diff --git a/xedit.c b/xedit.c
index 96f965bf9fa9ef0efebae7d1bfb210077788c762..fa523b6e3843a01e61f777ef3be6a13b1646dd2a 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -7,13 +7,7 @@
 
 #include "edit.h"
 
-#define BKGCLR (clr(CLR_BASE03))
-#define GTRCLR (clr(CLR_BASE02))
-#define CSRCLR (clr(CLR_BASE3))
-#define TXTCLR (clr(CLR_BASE0))
-
 Buf Buffer;
-unsigned CursorPos = 0;
 unsigned TargetCol = 0;
 unsigned DotBeg = 0;
 unsigned DotEnd = 0;
@@ -173,6 +167,8 @@ static void deinit(void) {
 static int init(void) {
     atexit(deinit);
     signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal
+    setlocale(LC_CTYPE, "");
+    XSetLocaleModifiers("");
     /* open the X display and get basic attributes */
     if (!(X.display = XOpenDisplay(0)))
         die("cannot open display");
@@ -275,7 +271,7 @@ static MouseEvent* getmouse(XEvent* e) {
     static MouseEvent event;
     if (e->type == MotionNotify) {
         event.type   = MouseMove;
-        event.button = MOUSE_NONE;
+        event.button = MOUSE_LEFT;
         event.x      = e->xmotion.x / Fonts.base.width;
         event.y      = e->xmotion.y / Fonts.base.height;
     } else {
@@ -297,10 +293,11 @@ static MouseEvent* getmouse(XEvent* e) {
 
 static void handle_event(XEvent* e) {
     switch (e->type) {
-        case FocusIn:     if (X.xic) XSetICFocus(X.xic);   break;
-        case FocusOut:    if (X.xic) XUnsetICFocus(X.xic); break;
-        case KeyPress:    handle_key(getkey(e));           break;
-        case ButtonPress: handle_mouse(getmouse(e));       break;
+        case FocusIn:      if (X.xic) XSetICFocus(X.xic);   break;
+        case FocusOut:     if (X.xic) XUnsetICFocus(X.xic); break;
+        case KeyPress:     handle_key(getkey(e));           break;
+        case ButtonPress:  handle_mouse(getmouse(e));       break;
+        case MotionNotify: handle_mouse(getmouse(e));       break;
         case ConfigureNotify: // Resize the window
             if (e->xconfigure.width != X.width || e->xconfigure.height != X.height) {
                 X.width  = e->xconfigure.width;
@@ -328,10 +325,10 @@ void draw_runes(unsigned x, unsigned y, XftColor* fg, XftColor* bg, UGlyph* glyp
 
 void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) {
     XftGlyphFontSpec specs[rlen];
-    int i = 0;
+    size_t i = 0;
     while (rlen) {
         int numspecs = 0;
-        int attr = glyphs[i].attr;
+        uint32_t attr = glyphs[i].attr;
         while (i < ncols && glyphs[i].attr == attr) {
             font_find(&(specs[numspecs]), glyphs[i].rune);
             specs[numspecs].x = x;
@@ -374,24 +371,24 @@ static void draw_cursor(unsigned csrx, unsigned csry) {
     UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth);
     csrrune->attr = (CLR_BASE3 << 8 | CLR_BASE03);
     if (Buffer.insert_mode) {
-        XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height);
+        XftDrawRect(X.xft, clr(CLR_BASE3), csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height);
     } else {
-        XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height);
+        XftDrawRect(X.xft, clr(CLR_BASE3), csrx * Fonts.base.width, (csry+1) * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height);
         draw_glyphs(csrx * Fonts.base.width, (csry+2) * Fonts.base.height, csrrune, 1, rwidth);
     }
 }
 
 static void redraw(void) {
-    uint32_t start = getmillis();
+    //uint32_t start = getmillis();
     /* draw the background colors */
-    XftDrawRect(X.xft, BKGCLR, 0, 0, X.width, X.height);
-    XftDrawRect(X.xft, GTRCLR, 79 * Fonts.base.width, 0, Fonts.base.width, X.height);
+    XftDrawRect(X.xft, clr(CLR_BASE03), 0, 0, X.width, X.height);
+    XftDrawRect(X.xft, clr(CLR_BASE02), 79 * Fonts.base.width, 0, Fonts.base.width, X.height);
     XftDrawRect(X.xft, clr(CLR_BASE02), 0, 0, X.width, Fonts.base.height);
     XftDrawRect(X.xft, clr(CLR_BASE01), 0, Fonts.base.height, X.width, 1);
 
     /* update the screen buffer and retrieve cursor coordinates */
     unsigned csrx, csry;
-    screen_update(&Buffer, CursorPos, &csrx, &csry);
+    screen_update(&Buffer, DotEnd, &csrx, &csry);
 
     /* flush the screen buffer */
     unsigned nrows, ncols;
@@ -408,7 +405,7 @@ static void redraw(void) {
     /* flush pixels to the screen */
     XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0);
     XFlush(X.display);
-    printf("refresh: %u\n", getmillis() - start);
+    //printf("refresh: %u\n", getmillis() - start);
 }
 
 int main(int argc, char** argv) {
@@ -416,10 +413,9 @@ int main(int argc, char** argv) {
     buf_init(&Buffer);
     if (argc > 1)
         buf_load(&Buffer, argv[1]);
-    /* main x11 event loop */
-    setlocale(LC_CTYPE, "");
-    XSetLocaleModifiers("");
+    /* initialize the display engine */
     init();
+    /* main x11 event loop */
     XEvent e;
     while (true) {
         XPeekEvent(X.display,&e);