]> git.mdlowis.com Git - projs/tide.git/commitdiff
Added preliminary support for copy paste
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 10 Nov 2016 14:02:13 +0000 (09:02 -0500)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 10 Nov 2016 14:02:13 +0000 (09:02 -0500)
Makefile
inc/edit.h
libedit/buf.c
libedit/clip.c [new file with mode: 0644]
libedit/exec.c [new file with mode: 0644]
libedit/keyboard.c
libedit/utils.c

index 7ee3306dbbcb23df51deb2adf87d638e3ed16466..f9a3e95e2196126f06bb81da64a3391b9d5aa1ea 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,3 @@
-
 INCS = -Iinc/
 
 LIBEDIT_OBJS =         \
@@ -8,7 +7,9 @@ LIBEDIT_OBJS =         \
        libedit/mouse.o    \
        libedit/screen.o   \
        libedit/utf8.o     \
-       libedit/utils.o
+       libedit/utils.o    \
+       libedit/exec.o     \
+       libedit/clip.o
 
 LIBX_OBJS = \
        libx/x11.o
index 80d4693d3fa0e8b75ab70cf7777f512354519d62..c294c4766e07298045375fda31c4405498572a4e 100644 (file)
@@ -11,6 +11,7 @@ uint32_t getmillis(void);
 bool risword(Rune r);
 bool risblank(Rune r);
 char* stringdup(const char* str);
+char* fdgets(int fd);
 
 /* Buffer management functions
  *****************************************************************************/
@@ -69,6 +70,8 @@ unsigned buf_byrune(Buf* buf, unsigned pos, int count);
 unsigned buf_byline(Buf* buf, unsigned pos, int count);
 unsigned buf_getcol(Buf* buf, unsigned pos);
 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);
 
 /* Charset Handling
  *****************************************************************************/
@@ -134,6 +137,26 @@ void screen_clearrow(unsigned row);
 unsigned screen_setcell(unsigned row, unsigned col, uint32_t attr, Rune r);
 UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth);
 
+/* Command Executions
+ *****************************************************************************/
+typedef struct {
+    int pid;
+    int in;
+    int out;
+    int err;
+} Process;
+
+int execute(char** cmd, Process* proc);
+void detach(Process* proc);
+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 */
index 8f017a7450a87a28398980e15f33a8fdbc9e5239..8382d56d6e84563a1588d669c119de1526c03bc0 100644 (file)
@@ -348,3 +348,43 @@ unsigned buf_setcol(Buf* buf, unsigned pos, unsigned col) {
     }
     return curr;
 }
+
+char* buf_getstr(Buf* buf, unsigned beg, unsigned end) {
+    char utf[UTF_MAX] = {0};
+    size_t len = 0;
+    char*  str = NULL;
+    for (; beg <= end; beg++) {
+        Rune rune = buf_get(buf, beg);
+        if (rune == RUNE_CRLF) {
+            str = realloc(str, len + 2);
+            str[len + 1] = '\r';
+            str[len + 2] = '\n';
+            len += 2;
+        } else {
+            size_t n = utf8encode(utf, rune);
+            str = realloc(str, len + n);
+            memcpy(str+len, utf, n);
+            len += n;
+        }
+    }
+    str = realloc(str, len+1);
+    if (str) str[len] = '\0';
+    return str;
+}
+
+unsigned buf_putstr(Buf* buf, unsigned beg, unsigned end, char* str) {
+    bool locked = buf_locked(buf);
+    buf_setlocked(buf, false);
+    /* delete the selected text first */
+    for (unsigned i = beg; ((end-beg) > 1) && (i <= end); i++)
+        buf_del(buf, beg);
+    /* insert the text */
+    while (*str) {
+        Rune rune = 0;
+        size_t length = 0;
+        while (!utf8decode(&rune, &length, *str++));
+        buf_ins(buf, beg++, rune);
+    }
+    buf_setlocked(buf, locked);
+    return beg;
+}
diff --git a/libedit/clip.c b/libedit/clip.c
new file mode 100644 (file)
index 0000000..f1b0644
--- /dev/null
@@ -0,0 +1,20 @@
+#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/exec.c b/libedit/exec.c
new file mode 100644 (file)
index 0000000..e90bfda
--- /dev/null
@@ -0,0 +1,85 @@
+#include <stdc.h>
+#include <utf.h>
+#include <edit.h>
+
+#define _POSIX_C_SOURCE 200809L
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+
+int execute(char** cmd, Process* proc) {
+    int inpipe[2], outpipe[2], errpipe[2];
+    /* create the pipes */
+    if ((pipe(inpipe) < 0) || (pipe(outpipe) < 0) || (pipe(errpipe) < 0))
+        return -1;
+    /* create the process */
+    proc->pid = fork();
+    if (proc->pid < 0) {
+        /* signal that we failed to fork */
+        proc->in  = -1;
+        proc->out = -1;
+        proc->err = -1;
+    } else if (0 == proc->pid) {
+        /* redirect child process's io to the pipes */
+        if ((dup2(inpipe[PIPE_READ], STDIN_FILENO) < 0)    ||
+            (dup2(outpipe[PIPE_WRITE], STDOUT_FILENO) < 0) ||
+            (dup2(errpipe[PIPE_WRITE], STDERR_FILENO) < 0)) {
+            perror("failed to pipe");
+            exit(1);
+        }
+        /* execute the process */
+        close(inpipe[PIPE_WRITE]);
+        close(outpipe[PIPE_READ]);
+        close(errpipe[PIPE_READ]);
+        exit(execvp(cmd[0], cmd));
+    } else {
+        close(inpipe[PIPE_READ]);
+        close(outpipe[PIPE_WRITE]);
+        close(errpipe[PIPE_WRITE]);
+        proc->in   = inpipe[PIPE_WRITE];
+        proc->out  = outpipe[PIPE_READ];
+        proc->err  = errpipe[PIPE_READ];
+    }
+    return proc->pid;
+}
+
+void detach(Process* proc) {
+    close(proc->in);
+    close(proc->out);
+    close(proc->err);
+}
+
+void terminate(Process* proc, int sig) {
+    detach(proc);
+    kill(proc->pid, sig);
+}
+
+char* cmdread(char** cmd) {
+    Process proc;
+    if (execute(cmd, &proc) < 0) {
+        perror("failed to execute");
+        return NULL;
+    }
+    char* str = fdgets(proc.out);
+    detach(&proc);
+    waitpid(proc.pid, NULL, 0);
+    return str;
+}
+
+void cmdwrite(char** cmd, char* text) {
+    Process proc;
+    if (execute(cmd, &proc) < 0) {
+        perror("failed to execute");
+        return;
+    }
+    if (write(proc.in, text, strlen(text)) < 0) {
+        perror("failed to write");
+        return;
+    }
+    detach(&proc);
+    waitpid(proc.pid, NULL, 0);
+}
index c05df34def76be63e9d18cf291412f5b7e969e4b..d530e32534a21a6890850ea0abff6047eaa4dd0a 100644 (file)
@@ -127,6 +127,20 @@ static void redo(void) {
 
 /*****************************************************************************/
 
+static void yank_selection(void) {
+    char* str = buf_getstr(&Buffer, SelBeg, SelEnd);
+    clipcopy(str);
+    free(str);
+}
+
+static void paste_after(void) {
+    char* str = clippaste();
+    buf_putstr(&Buffer, SelBeg, SelEnd, str);
+    free(str);
+}
+
+/*****************************************************************************/
+
 typedef struct {
     Rune key;
     void (*action)(void);
@@ -181,9 +195,9 @@ static KeyBinding_T Normal[] = {
     { KEY_DELETE, dot_delete    },
 
     /* Copy/Paste */
-    //{ 'y',        yank_selection },
+    { 'y',        yank_selection },
+    { 'p',        paste_after    },
     //{ 'Y',        yank_line      },
-    //{ 'p',        paste_after    },
     //{ 'P',        paste_before   },
 
     /* context sensitive language */
index bfe5ca617f646a240182f70f579f5327709616d5..4aae69f9c611450f769ba9b57766fb44d6a6fe9e 100644 (file)
@@ -73,3 +73,16 @@ char* stringdup(const char* s) {
     strcpy(ns,s);
     return ns;
 }
+
+char* fdgets(int fd) {
+    char buf[256];
+    size_t len = 0, nread = 0;
+    char* str = NULL;
+    while ((nread = read(fd, buf, 256)) > 0) {
+        str = realloc(str, len + nread + 1);
+        memcpy(str+len, buf, nread);
+        len += nread;
+    }
+    if (str) str[len] = '\0';
+    return str;
+}