summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-08-20 18:41:23 -0400
committerJune McEnroe <june@causal.agency>2018-08-20 18:43:16 -0400
commit4e4eb0de0f50517e3a2892cddcadfbd75da7152f (patch)
treecebf2ed9f1cc63b5714e2c9357f8b9ff27f10afc
parentSet errno in vaswprintf in case vswprintf does not (diff)
downloadcatgirl-4e4eb0de0f50517e3a2892cddcadfbd75da7152f.tar.gz
catgirl-4e4eb0de0f50517e3a2892cddcadfbd75da7152f.zip
Add wcsnchr, wcsnrchr, awcsntombs
This eliminates calls to editHead and editTail inside edit.c.

Oh god I'm sorry for following libc naming conventions for this stuff.
-rw-r--r--chat.h3
-rw-r--r--edit.c15
-rw-r--r--pls.c32
3 files changed, 40 insertions, 10 deletions
diff --git a/chat.h b/chat.h
index 4975a3e..4ec5dcd 100644
--- a/chat.h
+++ b/chat.h
@@ -161,8 +161,11 @@ void logFmt(
 
 void spawn(char *const argv[]);
 
+wchar_t *wcsnchr(const wchar_t *wcs, size_t len, wchar_t chr);
+wchar_t *wcsnrchr(const wchar_t *wcs, size_t len, wchar_t chr);
 wchar_t *ambstowcs(const char *src);
 char *awcstombs(const wchar_t *src);
+char *awcsntombs(const wchar_t *src, size_t nwc);
 int vaswprintf(wchar_t **ret, const wchar_t *format, va_list ap);
 
 // HACK: clang won't check wchar_t *format strings.
diff --git a/edit.c b/edit.c
index 8db92fc..782f449 100644
--- a/edit.c
+++ b/edit.c
@@ -57,15 +57,12 @@ static void right(void) {
 
 static void backWord(void) {
 	left();
-	editHead();
-	wchar_t *word = wcsrchr(line.buf, ' ');
-	editTail();
+	wchar_t *word = wcsnrchr(line.buf, line.ptr - line.buf, L' ');
 	line.ptr = (word ? &word[1] : line.buf);
 }
 static void foreWord(void) {
 	right();
-	editTail();
-	wchar_t *word = wcschr(line.ptr, ' ');
+	wchar_t *word = wcsnchr(line.ptr, line.end - line.ptr, L' ');
 	line.ptr = (word ? word : line.end);
 }
 
@@ -108,12 +105,10 @@ static void killForeWord(void) {
 static char *prefix;
 static void complete(struct Tag tag) {
 	if (!line.tab) {
-		editHead();
-		line.tab = wcsrchr(line.buf, L' ');
+		line.tab = wcsnrchr(line.buf, line.ptr - line.buf, L' ');
 		line.tab = (line.tab ? &line.tab[1] : line.buf);
-		prefix = awcstombs(line.tab);
+		prefix = awcsntombs(line.tab, line.ptr - line.tab);
 		if (!prefix) err(EX_DATAERR, "awcstombs");
-		editTail();
 	}
 
 	const char *next = tabNext(tag, prefix);
@@ -161,7 +156,7 @@ static void reject(void) {
 
 static void enter(struct Tag tag) {
 	if (line.end == line.buf) return;
-	editTail();
+	*line.end = L'\0';
 	char *str = awcstombs(line.buf);
 	if (!str) err(EX_DATAERR, "awcstombs");
 	input(tag, str);
diff --git a/pls.c b/pls.c
index d768b8f..08309f8 100644
--- a/pls.c
+++ b/pls.c
@@ -22,6 +22,22 @@
 
 #include "chat.h"
 
+wchar_t *wcsnchr(const wchar_t *wcs, size_t len, wchar_t chr) {
+	len = wcsnlen(wcs, len);
+	for (size_t i = 0; i < len; ++i) {
+		if (wcs[i] == chr) return (wchar_t *)&wcs[i];
+	}
+	return NULL;
+}
+
+wchar_t *wcsnrchr(const wchar_t *wcs, size_t len, wchar_t chr) {
+	len = wcsnlen(wcs, len);
+	for (size_t i = len - 1; i < len; --i) {
+		if (wcs[i] == chr) return (wchar_t *)&wcs[i];
+	}
+	return NULL;
+}
+
 wchar_t *ambstowcs(const char *src) {
 	size_t len = mbsrtowcs(NULL, &src, 0, NULL);
 	if (len == (size_t)-1) return NULL;
@@ -54,6 +70,22 @@ char *awcstombs(const wchar_t *src) {
 	return dst;
 }
 
+char *awcsntombs(const wchar_t *src, size_t nwc) {
+	size_t len = wcsnrtombs(NULL, &src, nwc, 0, NULL);
+	if (len == (size_t)-1) return NULL;
+
+	char *dst = malloc(sizeof(*dst) * (1 + len));
+	if (!dst) return NULL;
+
+	len = wcsnrtombs(dst, &src, nwc, 1 + len, NULL);
+	if (len == (size_t)-1) {
+		free(dst);
+		return NULL;
+	}
+
+	return dst;
+}
+
 // From <https://en.cppreference.com/w/c/io/fwprintf#Notes>:
 //
 // While narrow strings provide snprintf, which makes it possible to determine