]> git.mdlowis.com Git - projs/tide.git/commitdiff
first pass at simplified non-modal editor
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 10 Nov 2016 18:37:07 +0000 (13:37 -0500)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 10 Nov 2016 18:37:07 +0000 (13:37 -0500)
inc/edit.h
libedit/keyboard.c
xedit.c

index c294c4766e07298045375fda31c4405498572a4e..17740ca0a4760ebcb93738d0fcd3a34c38d0f6b4 100644 (file)
@@ -47,6 +47,11 @@ typedef struct buf {
     Log* redo;      /* redo list */
 } Buf;
 
+typedef struct {
+    size_t beg;
+    size_t end;
+} Sel;
+
 void buf_load(Buf* buf, char* path);
 void buf_save(Buf* buf);
 void buf_init(Buf* buf);
@@ -73,6 +78,34 @@ unsigned buf_setcol(Buf* buf, unsigned pos, unsigned col);
 char* buf_getstr(Buf* buf, unsigned beg, unsigned end);
 unsigned buf_putstr(Buf* buf, unsigned beg, unsigned end, char* str);
 
+/*
+void buf_load(Buf* buf, char* path);
+void buf_save(Buf* buf);
+void buf_init(Buf* buf);
+void buf_ins(Buf* buf, Sel csr, Rune);
+void buf_del(Buf* buf, Sel csr);
+Sel buf_undo(Buf* buf, Sel csr);
+Sel buf_redo(Buf* buf, Sel csr);
+Rune buf_get(Buf* buf, Sel csr);
+void buf_setlocked(Buf* buf, bool locked);
+bool buf_locked(Buf* buf);
+bool buf_iseol(Buf* buf, Sel csr);
+Sel buf_bol(Buf* buf, Sel csr);
+Sel buf_eol(Buf* buf, Sel csr);
+Sel buf_bow(Buf* buf, Sel csr);
+Sel buf_eow(Buf* buf, Sel csr);
+Sel buf_lscan(Buf* buf, Sel csr, Rune r);
+Sel buf_rscan(Buf* buf, Sel csr, Rune r);
+Sel buf_find(Buf* buf, Sel csr);
+Sel buf_end(Buf* buf);
+Sel buf_byrune(Buf* buf, Sel csr, int count);
+Sel buf_byline(Buf* buf, Sel csr, int count);
+Sel buf_getcol(Buf* buf, Sel csr);
+Sel buf_setcol(Buf* buf, Sel csr, unsigned col);
+char* buf_getstr(Buf* buf, Sel csr);
+Sel buf_putstr(Buf* buf, Sel csr, char* str);
+*/
+
 /* Charset Handling
  *****************************************************************************/
 enum {
index d530e32534a21a6890850ea0abff6047eaa4dd0a..e79d79966204d6466e09e24a8674485ea7265286 100644 (file)
@@ -121,7 +121,7 @@ static void undo(void) {
 }
 
 static void redo(void) {
-    SelBeg = SelEnd = buf_redo(&Buffer, SelEnd);
+    SelBeg = SelEnd = buf_redo(&Buffer, SelEnd)+1;
     TargetCol = buf_getcol(&Buffer, SelEnd);
 }
 
diff --git a/xedit.c b/xedit.c
index 0d9c4913aeb165f6b70f07ebba4f12af4430bf36..99b60556abd5cae3ed22bce7f1742a664e954441 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -2,9 +2,27 @@
 #include <X.h>
 #include <utf.h>
 #include <edit.h>
+#include <ctype.h>
 
 static void redraw(int width, int height);
 static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y);
+void handle_key(Rune key);
+
+static void quit(void);
+static void write(void);
+static void undo(void);
+static void redo(void);
+static void cut(void);
+static void copy(void);
+static void paste(void);
+static void cursor_up(void);
+static void cursor_dn(void);
+static void cursor_left(void);
+static void cursor_right(void);
+static void cursor_bol(void);
+static void cursor_eol(void);
+static void dot_delete(void);
+static void dot_backspace(void);
 
 Buf Buffer;
 unsigned TargetCol = 0;
@@ -37,6 +55,151 @@ static XConfig Config = {
     }
 };
 
+typedef struct {
+    Rune key;
+    void (*action)(void);
+} KeyBinding_T;
+
+static KeyBinding_T Insert[] = {
+    { KEY_CTRL_Q,    quit          },
+    { KEY_CTRL_S,    write         },
+    { 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,    dot_delete    },
+    { KEY_BACKSPACE, dot_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);
+}
+
+void handle_key(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);
+}
+
+static void quit(void) {
+    static uint32_t num_clicks = 0;
+    static uint32_t prevtime = 0;
+    uint32_t now = getmillis();
+    num_clicks = (now - prevtime < 250 ? num_clicks+1 : 1);
+    prevtime = now;
+    if (!Buffer.modified || num_clicks >= 2)
+        exit(0);
+}
+
+static void write(void) {
+    buf_save(&Buffer);
+}
+
+static void undo(void) {
+    SelBeg = SelEnd = buf_undo(&Buffer, SelEnd);
+    TargetCol = buf_getcol(&Buffer, SelEnd);
+}
+
+static void redo(void) {
+    SelBeg = SelEnd = buf_redo(&Buffer, SelEnd);
+    TargetCol = buf_getcol(&Buffer, SelEnd);
+}
+
+static void cut(void) {
+    char* str = buf_getstr(&Buffer, SelBeg, SelEnd);
+    clipcopy(str);
+    free(str);
+    dot_delete();
+}
+
+static void copy(void) {
+    char* str = buf_getstr(&Buffer, SelBeg, SelEnd);
+    clipcopy(str);
+    free(str);
+}
+
+static void paste(void) {
+    char* str = clippaste();
+    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;
+}
+
+static void cursor_eol(void) {
+    SelBeg = SelEnd = buf_eol(&Buffer, SelEnd);
+    TargetCol = (unsigned)-1;
+}
+
+static void dot_delete(void) {
+    if (SelEnd == buf_end(&Buffer)) return;
+    size_t n = SelEnd - SelBeg;
+    bool locked = buf_locked(&Buffer);
+    if (locked || !n) n++;
+    buf_setlocked(&Buffer,false);
+    for (size_t i = 0; i < n; i++)
+        buf_del(&Buffer, SelBeg);
+    SelEnd = SelBeg;
+    TargetCol = buf_getcol(&Buffer, SelEnd);
+    buf_setlocked(&Buffer, locked);
+}
+
+static void dot_backspace(void) {
+    if (SelBeg > 0 && SelBeg == SelEnd) SelBeg--;
+    while (SelBeg < SelEnd)
+        buf_del(&Buffer, --SelEnd);
+    TargetCol = buf_getcol(&Buffer, SelEnd);
+}
+
 static void draw_runes(unsigned x, unsigned y, int fg, int bg, UGlyph* glyphs, size_t rlen) {
     XftGlyphFontSpec specs[rlen];
     while (rlen) {
@@ -90,18 +253,6 @@ static void draw_status(int fg, unsigned ncols) {
     draw_runes(0, 0, fg, 0, glyphs, status - glyphs);
 }
 
-static void draw_cursor(unsigned csrx, unsigned csry) {
-    unsigned rwidth;
-    UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth);
-    csrrune->attr = (CLR_BASE3 << 8 | CLR_BASE03);
-    if (buf_locked(&Buffer)) {
-        x11_draw_rect(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);
-    } else {
-        x11_draw_rect(CLR_BASE3, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height);
-    }
-}
-
 static void redraw(int width, int height) {
     /* update the screen size if needed */
     screen_setsize(&Buffer,
@@ -128,7 +279,7 @@ static void redraw(int width, int height) {
     }
 
     /* Place cursor on screen */
-    draw_cursor(csrx, csry);
+    x11_draw_rect(CLR_BASE3, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height);
 }
 
 static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) {
@@ -146,6 +297,7 @@ int main(int argc, char** argv) {
     buf_init(&Buffer);
     if (argc > 1)
         buf_load(&Buffer, argv[1]);
+    buf_setlocked(&Buffer, false);
     /* initialize the display engine */
     x11_init(&Config);
     x11_window("edit", Width, Height);