diff options
author | June McEnroe <june@causal.agency> | 2018-08-20 18:41:23 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2018-08-20 18:43:16 -0400 |
commit | 4e4eb0de0f50517e3a2892cddcadfbd75da7152f (patch) | |
tree | cebf2ed9f1cc63b5714e2c9357f8b9ff27f10afc | |
parent | Set errno in vaswprintf in case vswprintf does not (diff) | |
download | catgirl-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.h | 3 | ||||
-rw-r--r-- | edit.c | 15 | ||||
-rw-r--r-- | pls.c | 32 |
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 |