summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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