about summary refs log tree commit diff
path: root/input.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2022-02-20 14:37:51 -0500
committerJune McEnroe <june@causal.agency>2022-02-20 14:37:51 -0500
commit012fd67539cdf1c13edbb6047253e168d1814cd3 (patch)
treea9f8efee3b691b11a030e118f3c1f891098df20e /input.c
parentMake sure new cap is actually larger than new length (diff)
downloadcatgirl-012fd67539cdf1c13edbb6047253e168d1814cd3.tar.gz
catgirl-012fd67539cdf1c13edbb6047253e168d1814cd3.zip
Use separate edit buffers for each ID
Diffstat (limited to '')
-rw-r--r--input.c120
1 files changed, 65 insertions, 55 deletions
diff --git a/input.c b/input.c
index ba83762..b578d17 100644
--- a/input.c
+++ b/input.c
@@ -89,7 +89,7 @@ enum {
 #undef X
 };
 
-static struct Edit edit;
+static struct Edit edits[IDCap];
 
 void inputInit(void) {
 	struct termios term;
@@ -160,7 +160,7 @@ static char *inputStop(
 
 void inputUpdate(void) {
 	uint id = windowID();
-	char *buf = editString(&edit);
+	char *buf = editString(&edits[id]);
 	if (!buf) err(EX_OSERR, "editString");
 
 	const char *prefix = "";
@@ -192,7 +192,7 @@ void inputUpdate(void) {
 	} else {
 		prompt = "";
 	}
-	if (skip > &buf[edit.mbs.pos]) {
+	if (skip > &buf[edits[id].mbs.pos]) {
 		prefix = prompt = suffix = "";
 		skip = buf;
 	}
@@ -211,7 +211,7 @@ void inputUpdate(void) {
 
 	int pos;
 	struct Style style = styleInput;
-	inputStop(styleInput, &style, skip, &buf[edit.mbs.pos]);
+	inputStop(styleInput, &style, skip, &buf[edits[id].mbs.pos]);
 	getyx(uiInput, y, pos);
 	wmove(uiInput, y, x);
 
@@ -276,14 +276,30 @@ static int macroExpand(struct Edit *e) {
 }
 
 static struct {
+	uint id;
 	char *pre;
 	size_t pos;
 	size_t len;
 	bool suffix;
 } tab;
 
+static void tabAccept(void) {
+	completeAccept();
+	tab.len = 0;
+}
+
+static void tabReject(void) {
+	completeReject();
+	tab.len = 0;
+}
+
 static int tabComplete(struct Edit *e, uint id) {
+	if (tab.len && id != tab.id) {
+		tabAccept();
+	}
+
 	if (!tab.len) {
+		tab.id = id;
 		tab.pos = e->pos;
 		while (tab.pos && !iswspace(e->buf[tab.pos-1])) tab.pos--;
 		tab.len = e->pos - tab.pos;
@@ -359,33 +375,25 @@ fail:
 	return -1;
 }
 
-static void tabAccept(void) {
-	completeAccept();
-	tab.len = 0;
-}
-
-static void tabReject(void) {
-	completeReject();
-	tab.len = 0;
-}
-
 static void inputEnter(void) {
-	char *cmd = editString(&edit);
+	uint id = windowID();
+	char *cmd = editString(&edits[id]);
 	if (!cmd) err(EX_OSERR, "editString");
 
 	tabAccept();
-	command(windowID(), cmd);
-	editFn(&edit, EditClear);
+	command(id, cmd);
+	editFn(&edits[id], EditClear);
 }
 
 static void keyCode(int code) {
 	int error = 0;
+	struct Edit *edit = &edits[windowID()];
 	switch (code) {
 		break; case KEY_RESIZE:  uiResize();
 		break; case KeyFocusIn:  windowUnmark();
 		break; case KeyFocusOut: windowMark();
 
-		break; case KeyMetaEnter: error = editInsert(&edit, L'\n');
+		break; case KeyMetaEnter: error = editInsert(edit, L'\n');
 		break; case KeyMetaEqual: windowToggleMute();
 		break; case KeyMetaMinus: windowToggleThresh(-1);
 		break; case KeyMetaPlus:  windowToggleThresh(+1);
@@ -396,32 +404,32 @@ static void keyCode(int code) {
 
 		break; case KeyMeta0 ... KeyMeta9: windowShow(code - KeyMeta0);
 		break; case KeyMetaA: windowAuto();
-		break; case KeyMetaB: error = editFn(&edit, EditPrevWord);
-		break; case KeyMetaD: error = editFn(&edit, EditDeleteNextWord);
-		break; case KeyMetaF: error = editFn(&edit, EditNextWord);
+		break; case KeyMetaB: error = editFn(edit, EditPrevWord);
+		break; case KeyMetaD: error = editFn(edit, EditDeleteNextWord);
+		break; case KeyMetaF: error = editFn(edit, EditNextWord);
 		break; case KeyMetaL: windowBare();
 		break; case KeyMetaM: uiWrite(windowID(), Warm, NULL, "");
 		break; case KeyMetaN: windowScroll(ScrollHot, +1);
 		break; case KeyMetaP: windowScroll(ScrollHot, -1);
-		break; case KeyMetaQ: error = editFn(&edit, EditCollapse);
+		break; case KeyMetaQ: error = editFn(edit, EditCollapse);
 		break; case KeyMetaS: uiSpoilerReveal ^= true; windowUpdate();
 		break; case KeyMetaT: windowToggleTime();
 		break; case KeyMetaU: windowScroll(ScrollUnread, 0);
 		break; case KeyMetaV: windowScroll(ScrollPage, +1);
 
-		break; case KeyCtrlLeft: error = editFn(&edit, EditPrevWord);
-		break; case KeyCtrlRight: error = editFn(&edit, EditNextWord);
+		break; case KeyCtrlLeft: error = editFn(edit, EditPrevWord);
+		break; case KeyCtrlRight: error = editFn(edit, EditNextWord);
 
-		break; case KEY_BACKSPACE: error = editFn(&edit, EditDeletePrev);
-		break; case KEY_DC: error = editFn(&edit, EditDeleteNext);
+		break; case KEY_BACKSPACE: error = editFn(edit, EditDeletePrev);
+		break; case KEY_DC: error = editFn(edit, EditDeleteNext);
 		break; case KEY_DOWN: windowScroll(ScrollOne, -1);
-		break; case KEY_END: error = editFn(&edit, EditTail);
+		break; case KEY_END: error = editFn(edit, EditTail);
 		break; case KEY_ENTER: inputEnter();
-		break; case KEY_HOME: error = editFn(&edit, EditHead);
-		break; case KEY_LEFT: error = editFn(&edit, EditPrev);
+		break; case KEY_HOME: error = editFn(edit, EditHead);
+		break; case KEY_LEFT: error = editFn(edit, EditPrev);
 		break; case KEY_NPAGE: windowScroll(ScrollPage, -1);
 		break; case KEY_PPAGE: windowScroll(ScrollPage, +1);
-		break; case KEY_RIGHT: error = editFn(&edit, EditNext);
+		break; case KEY_RIGHT: error = editFn(edit, EditNext);
 		break; case KEY_SEND: windowScroll(ScrollAll, -1);
 		break; case KEY_SHOME: windowScroll(ScrollAll, +1);
 		break; case KEY_UP: windowScroll(ScrollOne, +1);
@@ -431,29 +439,30 @@ static void keyCode(int code) {
 
 static void keyCtrl(wchar_t ch) {
 	int error = 0;
+	struct Edit *edit = &edits[windowID()];
 	switch (ch ^ L'@') {
-		break; case L'?': error = editFn(&edit, EditDeletePrev);
-		break; case L'A': error = editFn(&edit, EditHead);
-		break; case L'B': error = editFn(&edit, EditPrev);
+		break; case L'?': error = editFn(edit, EditDeletePrev);
+		break; case L'A': error = editFn(edit, EditHead);
+		break; case L'B': error = editFn(edit, EditPrev);
 		break; case L'C': raise(SIGINT);
-		break; case L'D': error = editFn(&edit, EditDeleteNext);
-		break; case L'E': error = editFn(&edit, EditTail);
-		break; case L'F': error = editFn(&edit, EditNext);
-		break; case L'H': error = editFn(&edit, EditDeletePrev);
-		break; case L'I': error = tabComplete(&edit, windowID());
+		break; case L'D': error = editFn(edit, EditDeleteNext);
+		break; case L'E': error = editFn(edit, EditTail);
+		break; case L'F': error = editFn(edit, EditNext);
+		break; case L'H': error = editFn(edit, EditDeletePrev);
+		break; case L'I': error = tabComplete(edit, windowID());
 		break; case L'J': inputEnter();
-		break; case L'K': error = editFn(&edit, EditDeleteTail);
+		break; case L'K': error = editFn(edit, EditDeleteTail);
 		break; case L'L': clearok(curscr, true);
 		break; case L'N': windowShow(windowNum() + 1);
 		break; case L'P': windowShow(windowNum() - 1);
-		break; case L'R': windowSearch(editString(&edit), -1);
-		break; case L'S': windowSearch(editString(&edit), +1);
-		break; case L'T': error = editFn(&edit, EditTranspose);
-		break; case L'U': error = editFn(&edit, EditDeleteHead);
+		break; case L'R': windowSearch(editString(edit), -1);
+		break; case L'S': windowSearch(editString(edit), +1);
+		break; case L'T': error = editFn(edit, EditTranspose);
+		break; case L'U': error = editFn(edit, EditDeleteHead);
 		break; case L'V': windowScroll(ScrollPage, -1);
-		break; case L'W': error = editFn(&edit, EditDeletePrevWord);
-		break; case L'X': error = macroExpand(&edit); tabAccept();
-		break; case L'Y': error = editFn(&edit, EditPaste);
+		break; case L'W': error = editFn(edit, EditDeletePrevWord);
+		break; case L'X': error = macroExpand(edit); tabAccept();
+		break; case L'Y': error = editFn(edit, EditPaste);
 	}
 	if (error) err(EX_OSERR, "editFn");
 }
@@ -488,8 +497,9 @@ static void keyStyle(wchar_t ch) {
 	if (color != Default) {
 		snprintf(buf, sizeof(buf), "%c%02d", C, color);
 	}
+	struct Edit *edit = &edits[windowID()];
 	for (char *ch = buf; *ch; ++ch) {
-		int error = editInsert(&edit, *ch);
+		int error = editInsert(edit, *ch);
 		if (error) err(EX_OSERR, "editInsert");
 	}
 }
@@ -514,8 +524,8 @@ void inputRead(void) {
 	wint_t ch;
 	static bool paste, style, literal;
 	for (int ret; ERR != (ret = wget_wch(uiInput, &ch));) {
-		bool tab = false;
-		size_t pos = edit.pos;
+		bool tabbing = false;
+		size_t pos = edits[tab.id].pos;
 		bool spr = uiSpoilerReveal;
 
 		if (ret == KEY_CODE_YES && ch == KeyPasteOn) {
@@ -525,7 +535,7 @@ void inputRead(void) {
 		} else if (ret == KEY_CODE_YES && ch == KeyPasteManual) {
 			paste ^= true;
 		} else if (paste || literal) {
-			int error = editInsert(&edit, ch);
+			int error = editInsert(&edits[windowID()], ch);
 			if (error) err(EX_OSERR, "editInsert");
 		} else if (ret == KEY_CODE_YES) {
 			keyCode(ch);
@@ -538,19 +548,19 @@ void inputRead(void) {
 		} else if (style) {
 			keyStyle(ch);
 		} else if (iswcntrl(ch)) {
-			tab = (ch == (L'I' ^ L'@'));
+			tabbing = (ch == (L'I' ^ L'@'));
 			keyCtrl(ch);
 		} else {
-			int error = editInsert(&edit, ch);
+			int error = editInsert(&edits[windowID()], ch);
 			if (error) err(EX_OSERR, "editInsert");
 		}
 		style = false;
 		literal = false;
 
-		if (!tab) {
-			if (edit.pos > pos) {
+		if (!tabbing) {
+			if (edits[tab.id].pos > pos) {
 				tabAccept();
-			} else if (edit.pos < pos) {
+			} else if (edits[tab.id].pos < pos) {
 				tabReject();
 			}
 		}