summary refs log tree commit diff
diff options
context:
space:
mode:
authorCurtis McEnroe2018-08-20 18:41:23 -0400
committerCurtis McEnroe2018-08-20 18:43:16 -0400
commit4e4eb0de0f50517e3a2892cddcadfbd75da7152f (patch)
treecebf2ed9f1cc63b5714e2c9357f8b9ff27f10afc
parentafae851319c543118f08b49b1fa804ef31e34267 (diff)
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