]> git.mdlowis.com Git - projs/tide.git/commitdiff
Crude prototype of terminal emulator functions now. Input/Output handling needs lots...
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 6 Jul 2017 19:45:39 +0000 (15:45 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 6 Jul 2017 19:45:39 +0000 (15:45 -0400)
inc/edit.h
inc/win.h
lib/win.c
lib/x11.c
pick.c
term.c
tests/tide.c
tide.c

index 00981bd63b793452e7e0b0e3bc4473d871fd3e82..411a0547da2f40711c39250d9c375452343bf890 100644 (file)
@@ -234,9 +234,6 @@ enum { /* Configuration Variables */
     ClrTagsSel, ClrTagsCsr, ClrEditNor, ClrEditSel, ClrEditCsr, ClrEditRul,
     ClrBorders,
 
-    //BkgRuler, BkgGutter, BkgTags, BkgEdit, BkgScroll, BkgThumb, BkgBorder,
-    //TxtCursor, TxtNormal, TxtSelected, TxtGutter, TxtCurrentLine,
-
     SynNormal, SynComment, SynConstant, SynString, SynChar, SynNumber,
     SynBoolean, SynFloat, SynVariable, SynFunction, SynKeyword, SynOperator,
     SynPreProc, SynType, SynStatement, SynSpecial
index 830628751b660dd8f9a8a398fadf8271672c9bf9..a54f0aaa86ffabf0580106c83bf71dcab0490dfa 100644 (file)
--- a/inc/win.h
+++ b/inc/win.h
@@ -46,7 +46,7 @@ void win_setlinenums(bool enable);
 bool win_getlinenums(void);
 void win_setruler(size_t ruler);
 Rune win_getkey(void);
-void win_setkeys(KeyBinding* bindings);
+void win_setkeys(KeyBinding* bindings, void (*inputfn)(Rune));
 void win_setmouse(MouseConfig* mconfig);
 void win_warpptr(WinRegion id);
 View* win_view(WinRegion id);
@@ -67,4 +67,5 @@ 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);
+bool update_needed(void);
 
index 5ba621db284e19f8afb0c4afbb9722ed0cd14325..59a2df6968087ec79fe916c44cf1312b5581bad8 100644 (file)
--- a/lib/win.c
+++ b/lib/win.c
@@ -11,6 +11,7 @@ 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 bool update_focus(void);
 static void draw_line_num(bool current, size_t x, size_t y, size_t gcols, size_t num);
 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);
@@ -31,6 +32,7 @@ static WinRegion Focused = EDIT;
 static Region Regions[NREGIONS] = {0};
 static Rune LastKey;
 static KeyBinding* Keys = NULL;
+static void (*InputFunc)(Rune);
 static bool ShowLineNumbers = false;
 
 static void win_init(void (*errfn)(char*)) {
@@ -58,27 +60,13 @@ void win_dialog(char* name, void (*errfn)(char*)) {
     x11_dialog(name, config_get_int(WinWidth), config_get_int(WinHeight));
 }
 
-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(config_get_int(EventTimeout));
         int nevents  = x11_events_queued();
-        if (update_focus() || pending || nevents) {
+        if (update_focus() || pending || nevents || update_needed()) {
             x11_events_take();
             if (x11_running())
                 x11_flip();
@@ -114,8 +102,9 @@ Rune win_getkey(void) {
     return LastKey;
 }
 
-void win_setkeys(KeyBinding* bindings) {
+void win_setkeys(KeyBinding* bindings, void (*inputfn)(Rune)) {
     Keys = bindings;
+    InputFunc = inputfn;
 }
 
 bool win_btnpressed(int btn) {
@@ -319,9 +308,13 @@ static void oninput(int mods, Rune key) {
     /* 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);
+        if (InputFunc) {
+            InputFunc(key);
+        } else {
+            if (key == '\n' && win_view(FOCUSED)->buffer.crlf)
+                key = RUNE_CRLF;
+            view_insert(win_view(FOCUSED), true, key);
+        }
     }
 }
 
@@ -390,6 +383,20 @@ static void onwheeldn(WinRegion id, bool pressed, size_t row, size_t col) {
     view_scroll(win_view(id), +(config_get_int(ScrollLines)));
 }
 
+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;
+}
+
 static void draw_line_num(bool current, size_t x, size_t y, size_t gcols, size_t num) {
     int color = config_get_int(ClrGutterNor);
     if (ShowLineNumbers) {
index 5e9e2cd43f468065ba64cc2d33148d26205a54b7..3e091c22a8812d838761db025ae2e14d7d0ba3b8 100644 (file)
--- a/lib/x11.c
+++ b/lib/x11.c
@@ -41,7 +41,7 @@ static struct {
     Colormap colormap;
     unsigned depth;
     int screen;
-    /* assume a single window for now. these are it's attributes */
+    /* assume a single window for now. these are its attributes */
     Window window;
     XftDraw* xft;
     Pixmap pixmap;
diff --git a/pick.c b/pick.c
index 801b9a310b36788f0cc61cba700169018536aaba..84d0087c0755f6a1aa7ff82f2924d31127ebbd63 100644 (file)
--- a/pick.c
+++ b/pick.c
@@ -170,6 +170,10 @@ void onshutdown(void) {
     x11_deinit();
 }
 
+bool update_needed(void) {
+    return false;
+}
+
 /* Main Routine
  *****************************************************************************/
 static void onerror(char* msg) {
@@ -224,7 +228,7 @@ int main(int argc, char** argv) {
     load_choices();
     if (vec_size(&Choices) > 1) {
         win_dialog("pick", onerror);
-        win_setkeys(Bindings);
+        win_setkeys(Bindings, NULL);
         win_settext(STATUS, (title ? title : "pick"));
         if (argc >= 2) {
             for (char* str = argv[1]; *str; str++)
diff --git a/term.c b/term.c
index f2aca6eff7118e523a1f40592d772a4d20e553a5..8dcd54dc67b5462d223d1e858a5b1ca2e943416b 100644 (file)
--- a/term.c
+++ b/term.c
+#define _XOPEN_SOURCE 700
 #include <stdc.h>
+#include <unistd.h>
+#ifdef __MACH__
+    #include <util.h>
+#else
+    #include <pty.h>
+#endif
+#include <poll.h>
+#include <termios.h>
+#include <sys/select.h>
+#include <sys/types.h>
 #include <x11.h>
 #include <utf.h>
 #include <edit.h>
 #include <ctype.h>
 #include <win.h>
 
-static int ShellFD;
+int CmdFD = -1;
+char* ShellCmd[] = { NULL, NULL };
 
-void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col) {
-}
+bool fdready(int fd);
 
-void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col) {
-}
+/* unused functions */
+void onfocus(bool focused) {}
 
-void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) {
+void onerror(char* msg) {
 }
 
 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) {
+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 onupdate(void) {
-}
-
-void onlayout(void) {
+    static char buf[8192];
+    long n;
+    if (!fdready(CmdFD)) return;
+    if ((n = read(CmdFD, buf, sizeof(buf))) < 0)
+        die("read() subprocess :");
+    for (long i = 0; i < n;) {
+        Rune rune = 0;
+        size_t length = 0;
+        while (!utf8decode(&rune, &length, buf[i++]));
+        view_insert(win_view(EDIT), false, rune);
+    }
 }
 
 void onshutdown(void) {
     x11_deinit();
 }
 
-void onerror(char* msg) {
+void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col) {
 }
 
-#ifndef TEST
-#include <unistd.h>
-#include <sys/ioctl.h>
-#ifdef __MACH__
-#include <util.h>
-#else
-#include <pty.h>
-#endif
+void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col) {
+}
 
-void spawn_shell(int master, int slave) {
-       static char* shell[] = { "/bin/sh", "-l", NULL };
-    dup2(slave, 0);
-    dup2(slave, 1);
-    dup2(slave, 2);
-    if (ioctl(slave, TIOCSCTTY, NULL) < 0)
-        die("ioctl(TIOSCTTY) failed");
-    close(slave);
-    close(master);
-    execvp(shell[0], shell);
+void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) {
 }
 
-int main(int argc, char** argv) {
-    int pid, m, s;
-       if (openpty(&m, &s, NULL, NULL, NULL) < 0)
-               die("openpty failed: %s\n", strerror(errno));
-    if ((pid = fork()))
-        die("fork failed");
-
-    if (pid == 0) {
-       spawn_shell(m, s);
-    } else {
-        close(s);
-        ShellFD = m;
-        //signal(SIGCHLD, sigchld);
+static void oninput(Rune rune) {
+    char c = (char)rune;
+    write(CmdFD, &c, 1);
+    view_insert(win_view(FOCUSED), false, rune);
+}
+
+bool update_needed(void) {
+    return fdready(CmdFD);
+}
+
+/******************************************************************************/
+
+bool fdready(int fd) {
+    fd_set fds;
+    FD_ZERO(&fds);
+    FD_SET(fd, &fds);
+    struct timeval tv = { .tv_usec = 0 };
+    return (select(fd+1, &fds, NULL, NULL, &tv) > 0);
+}
+
+int pty_spawn(char** argv) {
+    int fd;
+    struct termios tio;
+    pid_t pid;
+    putenv("TERM=dumb");
+    switch ( (pid = forkpty(&fd, NULL, NULL, NULL)) ) {
+        case -1: // Failed
+            die("forkpty() :");
+            break;
+
+        case 0: // Child Process
+            if (execvp(argv[0], argv) < 0)
+                die("execvp('%s', ...) :", argv[0]);
+            exit(EXIT_FAILURE);
+            break;
+
+        default: // Parent Process
+            tcgetattr(fd, &tio);
+            tio.c_lflag      &= ~(ECHO | ECHONL);
+            tio.c_cc[ VMIN ]  = 1;
+            tio.c_cc[ VTIME ] = 0;
+            tcsetattr(fd, TCSANOW, &tio);
+            break;
     }
+    return fd;
+}
 
+/******************************************************************************/
+
+#ifndef TEST
+int main(int argc, char** argv) {
+    if (!ShellCmd[0]) ShellCmd[0] = getenv("SHELL");
+    if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh";
+    CmdFD = pty_spawn(argc > 1 ? argv+1 : ShellCmd);
     win_window("term", onerror);
-    //win_setkeys(&Bindings);
-    //win_setmouse(&MouseHandlers);
+    win_setkeys(NULL, oninput);
+    win_buf(EDIT)->crlf = 1;
     win_loop();
-
     return 0;
 }
 #endif
index e6c97ace1e958d7b23a0279cacc3f186c5391520..044d199dfe86c3778b4140792f386d70052096f0 100644 (file)
@@ -25,8 +25,7 @@ static void initialize(void) {
     ShellCmd[0] = "/bin/sh";
     win_window("edit", ondiagmsg);
     XDisplay = XOpenDisplay(NULL);
-    win_setkeys(Bindings);
-    //win_setmouse(&MouseHandlers);
+    win_setkeys(Bindings, NULL);
 }
 
 /* Helper Functions
diff --git a/tide.c b/tide.c
index c93a76e7cddcee0512d753f5579b7ee7396b726f..6fcd3e4258d1cef579d535705e96b104ac297017 100644 (file)
--- a/tide.c
+++ b/tide.c
@@ -548,6 +548,10 @@ void onshutdown(void) {
     quit();
 }
 
+bool update_needed(void) {
+    return false;
+}
+
 void edit_relative(char* path) {
     char *currdir = NULL, *currpath = NULL, *relpath = NULL;
     char* origdir = getcurrdir();
@@ -617,7 +621,7 @@ int main(int argc, char** argv) {
         cmdrun(OpenCmd, NULL);
     }
     /* now create the window and start the event loop */
-    win_setkeys(Bindings);
+    win_setkeys(Bindings, NULL);
     win_loop();
     return 0;
 }