diff options
| -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
| @@ -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. @@ -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); @@ -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 | 
