summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--catgirl.12
-rw-r--r--chat.h1
-rw-r--r--edit.c26
-rw-r--r--ui.c7
4 files changed, 30 insertions, 6 deletions
diff --git a/catgirl.1 b/catgirl.1
index 752a9d2..2a3828d 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -226,6 +226,8 @@ Delete to end of line.
 Delete to beginning of line.
 .It Ic C-w
 Delete previous word.
+.It Ic C-y
+Paste previously deleted text.
 .It Ic M-b
 Move to previous word.
 .It Ic M-d
diff --git a/chat.h b/chat.h
index fc18b15..24360f0 100644
--- a/chat.h
+++ b/chat.h
@@ -157,6 +157,7 @@ enum Edit {
 	EditDeleteNext,
 	EditDeletePrevWord,
 	EditDeleteNextWord,
+	EditPaste,
 	EditInsert,
 	EditComplete,
 	EditEnter,
diff --git a/edit.c b/edit.c
index 47478ec..16fa910 100644
--- a/edit.c
+++ b/edit.c
@@ -16,6 +16,7 @@
 
 #include <assert.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <wchar.h>
@@ -46,14 +47,24 @@ char *editBuffer(size_t *mbsPos) {
 	return mbs;
 }
 
-static void reserve(size_t index, size_t count) {
-	if (len + count > Cap) return;
+static struct {
+	wchar_t buf[Cap];
+	size_t len;
+} cut;
+
+static bool reserve(size_t index, size_t count) {
+	if (len + count > Cap) return false;
 	memmove(&buf[index + count], &buf[index], sizeof(*buf) * (len - index));
 	len += count;
+	return true;
 }
 
 static void delete(size_t index, size_t count) {
 	if (index + count > len) return;
+	if (count > 1) {
+		memcpy(cut.buf, &buf[index], sizeof(*buf) * count);
+		cut.len = count;
+	}
 	memmove(
 		&buf[index], &buf[index + count], sizeof(*buf) * (len - index - count)
 	);
@@ -163,10 +174,17 @@ void edit(size_t id, enum Edit op, wchar_t ch) {
 			while (word < len && buf[word] != L' ') word++;
 			delete(pos, word - pos);
 		}
+		break; case EditPaste: {
+			if (reserve(pos, cut.len)) {
+				memcpy(&buf[pos], cut.buf, sizeof(*buf) * cut.len);
+				pos += cut.len;
+			}
+		}
 
 		break; case EditInsert: {
-			reserve(pos, 1);
-			if (pos < Cap) buf[pos++] = ch;
+			if (reserve(pos, 1)) {
+				buf[pos++] = ch;
+			}
 		}
 		break; case EditComplete: {
 			tabComplete(id);
diff --git a/ui.c b/ui.c
index 65b4760..d946854 100644
--- a/ui.c
+++ b/ui.c
@@ -166,12 +166,14 @@ void uiHide(void) {
 	endwin();
 }
 
-static void disableFlowControl(void) {
+// Gain use of C-q, C-s, C-z, C-y, C-o.
+static void acquireKeys(void) {
 	struct termios term;
 	int error = tcgetattr(STDOUT_FILENO, &term);
 	if (error) err(EX_OSERR, "tcgetattr");
 	term.c_iflag &= ~IXON;
 	term.c_cc[VSUSP] = _POSIX_VDISABLE;
+	term.c_cc[VDSUSP] = _POSIX_VDISABLE;
 	term.c_cc[VDISCARD] = _POSIX_VDISABLE;
 	error = tcsetattr(STDOUT_FILENO, TCSADRAIN, &term);
 	if (error) err(EX_OSERR, "tcsetattr");
@@ -212,7 +214,7 @@ void uiInit(void) {
 	initscr();
 	cbreak();
 	noecho();
-	disableFlowControl();
+	acquireKeys();
 	def_prog_mode();
 	atexit(errExit);
 	colorInit();
@@ -662,6 +664,7 @@ static void keyCtrl(wchar_t ch) {
 		break; case L'L': clearok(curscr, true);
 		break; case L'U': edit(id, EditDeleteHead, 0);
 		break; case L'W': edit(id, EditDeletePrevWord, 0);
+		break; case L'Y': edit(id, EditPaste, 0);
 	}
 }