From: Michael D. Lowis Date: Sat, 22 Oct 2016 01:55:14 +0000 (-0400) Subject: fleshed out the mouse selection logic a bit more X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=290b6a78488af41e90299aadd8462a5a13c52b78;p=projs%2Ftide.git fleshed out the mouse selection logic a bit more --- diff --git a/buf.c b/buf.c index 75533a6..601fccc 100644 --- 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 3d136a7..1c59866 100644 --- a/edit.h +++ b/edit.h @@ -5,18 +5,6 @@ #include #include -/* 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; diff --git a/keyboard.c b/keyboard.c index 4189d51..7220d74 100644 --- a/keyboard.c +++ b/keyboard.c @@ -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 f6c602d..87546e5 100644 --- 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 33e3392..f8d6c13 100644 --- a/utils.c +++ b/utils.c @@ -7,6 +7,7 @@ #include #include #include +#include #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 96f965b..fa523b6 100644 --- 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);