commit - 8947c1f29122ab2e506b2bb723a4fc92bd9d3a59
commit + 17e5106b8ecac061d8558f1d73f284c5516347cd
blob - 404312ec0aba8b3eca9ca668466fb8ffe6e5b933
blob + 17dd7e40516f85b94911879c02fb06aa540ab44a
--- telescope.h
+++ telescope.h
/* utf.8 */
uint32_t utf8_decode(uint32_t*restrict, uint32_t*restrict, uint8_t);
-void utf8_encode(uint32_t, char*);
+size_t utf8_encode(uint32_t, char*);
char *utf8_nth(char*, size_t);
size_t utf8_cplen(char*);
size_t utf8_chwidth(uint32_t);
size_t utf8_snwidth(const char*, size_t);
size_t utf8_swidth(const char*);
+size_t utf8_swidth_between(const char*, const char*);
+char *utf8_next_cp(char*);
+char *utf8_prev_cp(char*, char*);
/* util.c */
int mark_nonblock(int);
int has_prefix(const char*, const char*);
+int unicode_isspace(uint32_t);
+int unicode_isgraph(uint32_t);
void dispatch_imsg(struct imsgbuf*, imsg_handlerfn**, size_t);
/* wrap.c */
blob - ac2a27eb58345f3820fc77fe3e629e65c662714e
blob + ec6035aa0bce147c1c8b077104d6202d950a643b
--- ui.c
+++ ui.c
#include <telescope.h>
-#include <ctype.h>
#include <curses.h>
#include <event.h>
#include <locale.h>
char *curmesg;
char buf[1025];
- size_t off, len;
+ char *curs;
+ size_t cpoff;
char prompt[32];
void (*donefn)(void);
void (*abortfn)(void);
struct histhead *history;
struct hist *hist_cur;
- size_t hist_off;
+ size_t hist_off;
} ministate;
struct lineprefix {
&lu_history);
strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt));
strlcpy(ministate.buf, tab->hist_cur->h, sizeof(ministate.buf));
- ministate.off = strlen(tab->hist_cur->h);
- ministate.len = ministate.off;
+ ministate.curs = strchr(ministate.buf, '\0');
}
static void
enter_minibuffer(lu_self_insert, bp_select, exit_minibuffer, NULL);
strlcpy(ministate.prompt, "Bookmark URL: ", sizeof(ministate.prompt));
strlcpy(ministate.buf, tab->hist_cur->h, sizeof(ministate.buf));
- ministate.off = strlen(tab->hist_cur->h);
- ministate.len = ministate.off;
+ ministate.curs = strchr(ministate.buf, '\0');
}
static void
static void
cmd_mini_delete_char(struct tab *tab)
{
+ char *n;
+
minibuffer_taint_hist();
- if (ministate.len == 0 || ministate.off == ministate.len)
+ if (*(n = utf8_next_cp(ministate.curs)) == '\0')
return;
- memmove(&ministate.buf[ministate.off],
- &ministate.buf[ministate.off+1],
- ministate.len - ministate.off + 1);
- ministate.len--;
+ memmove(ministate.curs, n, strlen(n)+1);
}
static void
cmd_mini_delete_backward_char(struct tab *tab)
{
+ char *p;
+
minibuffer_taint_hist();
- if (ministate.len == 0 || ministate.off == 0)
+ if ((p = utf8_prev_cp(ministate.curs, ministate.buf)) == ministate.buf)
return;
- memmove(&ministate.buf[ministate.off-1],
- &ministate.buf[ministate.off],
- ministate.len - ministate.off + 1);
- ministate.off--;
- ministate.len--;
+ memmove(p, ministate.curs, strlen(ministate.curs)+1);
}
static void
cmd_mini_forward_char(struct tab *tab)
{
- if (ministate.off == ministate.len)
+ if (*ministate.curs == '\0')
return;
- ministate.off++;
+ ministate.curs = utf8_next_cp(ministate.curs);
+ ministate.cpoff++;
}
static void
cmd_mini_backward_char(struct tab *tab)
{
- if (ministate.off == 0)
+ if (ministate.cpoff == 0)
return;
- ministate.off--;
+ ministate.cpoff--;
+ ministate.curs = utf8_prev_cp(ministate.curs-1, ministate.buf);
}
static void
cmd_mini_move_end_of_line(struct tab *tab)
{
- ministate.off = ministate.len;
+ ministate.curs = strchr(ministate.buf, '\0');
+ ministate.cpoff = utf8_cplen(ministate.buf);
}
static void
cmd_mini_move_beginning_of_line(struct tab *tab)
{
- ministate.off = 0;
+ ministate.curs = ministate.buf;
+ ministate.cpoff = 0;
}
static void
cmd_mini_kill_line(struct tab *tab)
{
minibuffer_taint_hist();
-
- if (ministate.off == ministate.len)
- return;
- ministate.buf[ministate.off] = '\0';
- ministate.len -= ministate.off;
+ *ministate.curs = '\0';
}
static void
cmd_mini_abort(struct tab *tab)
{
- ministate.abortfn();
+ ministate.abortfn();
}
static void
ministate.hist_off--;
}
- if (ministate.hist_cur != NULL) {
- ministate.off = 0;
- ministate.len = strlen(ministate.hist_cur->h);
- }
+ if (ministate.hist_cur != NULL)
+ ministate.curs = ministate.hist_cur->h;
}
static void
ministate.hist_off++;
}
- if (ministate.hist_cur != NULL) {
- ministate.off = 0;
- ministate.len = strlen(ministate.hist_cur->h);
- }
+ if (ministate.hist_cur != NULL)
+ ministate.curs = ministate.hist_cur->h;
}
static void
static void
minibuffer_self_insert(void)
{
+ char tmp[5] = {0};
+ size_t len;
+
minibuffer_taint_hist();
- if (ministate.len == sizeof(ministate.buf) -1)
+ if (thiskey.cp == 0)
return;
- /* TODO: utf8 handling! */
+ len = utf8_encode(thiskey.cp, tmp);
+ if (ministate.curs + len > ministate.buf + sizeof(ministate.buf) - 1)
+ return;
- memmove(&ministate.buf[ministate.off+1],
- &ministate.buf[ministate.off],
- ministate.len - ministate.off + 1);
- ministate.buf[ministate.off] = thiskey.key;
- ministate.off++;
- ministate.len++;
+ memmove(ministate.curs + len, ministate.curs, strlen(ministate.curs)+1);
+ memcpy(ministate.curs, tmp, len);
+ ministate.curs = utf8_next_cp(ministate.curs);
+ ministate.cpoff++;
}
static void
eecmd_self_insert(void)
{
- if (thiskey.meta || isspace(thiskey.key) ||
- !isgraph(thiskey.key)) {
+ if (thiskey.meta || unicode_isspace(thiskey.cp) ||
+ !unicode_isgraph(thiskey.cp)) {
global_key_unbound();
return;
}
static void
lu_self_insert(void)
{
- if (thiskey.meta || isspace(thiskey.key) ||
- !isgraph(thiskey.key)) {
+ if (thiskey.meta || unicode_isspace(thiskey.key) ||
+ !unicode_isgraph(thiskey.key)) {
global_key_unbound();
return;
}
static void
redraw_minibuffer(void)
{
- size_t skip = 0, off_x = 0, off_y = 0;
struct tab *tab;
+ size_t off_y, off_x = 0;
+ char *start;
werase(minibuf);
+
if (in_minibuffer) {
mvwprintw(minibuf, 0, 0, "%s", ministate.prompt);
if (ministate.hist_cur != NULL)
getyx(minibuf, off_y, off_x);
- while (ministate.off - skip > (size_t)COLS / 2) {
- skip += MIN(ministate.off/4, 1);
+ start = ministate.hist_cur != NULL
+ ? ministate.hist_cur->h
+ : ministate.buf;
+ while (utf8_swidth_between(start, ministate.curs) > (size_t)COLS/2) {
+ start = utf8_next_cp(start);
}
- if (ministate.hist_cur != NULL)
- wprintw(minibuf, "%s", ministate.hist_cur->h + skip);
- else
- wprintw(minibuf, "%s", ministate.buf + skip);
+ waddstr(minibuf, start);
}
- if (ministate.curmesg != NULL) {
- if (in_minibuffer)
- wprintw(minibuf, " [%s]", ministate.curmesg);
- else
- wprintw(minibuf, "%s", ministate.curmesg);
- }
+ if (ministate.curmesg != NULL)
+ wprintw(minibuf, in_minibuffer ? " [%s]" : "%s",
+ ministate.curmesg);
if (!in_minibuffer && ministate.curmesg == NULL)
- wprintw(minibuf, "%s", keybuf);
+ waddstr(minibuf, keybuf);
/* If nothing else, show the URL at point */
if (!in_minibuffer && ministate.curmesg == NULL && *keybuf == '\0') {
tab = current_tab();
if (tab->s.current_line != NULL &&
tab->s.current_line->parent->type == LINE_LINK)
- wprintw(minibuf, "%s",
- tab->s.current_line->parent->alt);
+ waddstr(minibuf, tab->s.current_line->parent->alt);
}
if (in_minibuffer)
- wmove(minibuf, 0, off_x + ministate.off - skip);
+ wmove(minibuf, 0, off_x + utf8_swidth_between(start, ministate.curs));
}
static void
ministate.donefn = donefn;
ministate.abortfn = abortfn;
memset(ministate.buf, 0, sizeof(ministate.buf));
- ministate.off = 0;
- ministate.len = 0;
+ ministate.curs = ministate.buf;
+ ministate.cpoff = 0;
strlcpy(ministate.buf, "", sizeof(ministate.prompt));
ministate.history = hist;
blob - 127fbb5153f75ff8a6135564ac27df0b9d7ae17c
blob + 98aa6ca7aa2f966abcac792d28ef44e1c84b3624
--- utf8.c
+++ utf8.c
/* end of the converter, utility functions ahead */
/* encode cp in s. s must be at least 4 bytes wide */
-void
+size_t
utf8_encode(uint32_t cp, char *s)
{
if (cp <= 0x7F) {
*s = (uint8_t)cp;
+ return 1;
} else if (cp <= 0x7FF) {
s[1] = (uint8_t)(( cp & 0x3F ) + 0x80);
s[0] = (uint8_t)(((cp >> 6) & 0x1F) + 0xC0);
+ return 2;
} else if (cp <= 0xFFFF) {
s[2] = (uint8_t)(( cp & 0x3F) + 0x80);
s[1] = (uint8_t)(((cp >> 6) & 0x3F) + 0x80);
s[0] = (uint8_t)(((cp >> 12) & 0x0F) + 0xE0);
+ return 3;
} else if (cp <= 0x10FFFF) {
s[3] = (uint8_t)(( cp & 0x3F) + 0x80);
s[2] = (uint8_t)(((cp >> 6) & 0x3F) + 0x80);
s[1] = (uint8_t)(((cp >> 12) & 0x3F) + 0x80);
s[0] = (uint8_t)(((cp >> 18) & 0x07) + 0xF0);
- } else
- s[0] = '\0';
+ return 4;
+ } else {
+ s[0] = '\0';
+ return 0;
+ }
}
char *
return tot;
}
+
+size_t
+utf8_swidth_between(const char *str, const char *end)
+{
+ size_t tot;
+ uint32_t cp = 0, state = 0;
+
+ tot = 0;
+ for (; *str && str < end; ++str)
+ if (!utf8_decode(&state, &cp, *str))
+ tot += utf8_chwidth(cp);
+ return tot;
+}
+
+char *
+utf8_next_cp(char *s)
+{
+ uint32_t cp = 0, state = 0;
+
+ for (; *s; ++s)
+ if (!utf8_decode(&state, &cp, *s))
+ break;
+ return s+1;
+}
+
+char *
+utf8_prev_cp(char *start, char *base)
+{
+ uint8_t c;
+
+ for (; start > base; start--) {
+ c = *start;
+ if ((c & 0xC0) != 0x80)
+ return start;
+ }
+
+ return base;
+}
blob - 88a155f7dac24ee2cba73a819c8ed0e2fd51ae35
blob + 5d0267624c08d1c1f99cedfe2af9e7b944e563d8
--- util.c
+++ util.c
#include "telescope.h"
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
return prfx[i] == '\0';
}
+int
+unicode_isspace(uint32_t cp)
+{
+ if (cp < INT8_MAX)
+ return isspace(cp);
+ return 0;
+}
+
+int
+unicode_isgraph(uint32_t cp)
+{
+ if (cp < INT8_MAX)
+ return isgraph(cp);
+ return 1;
+}
+
void
dispatch_imsg(struct imsgbuf *ibuf, imsg_handlerfn **handlers, size_t size)
{