X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/9bb8630af3373e7bbf594bfeda731585684e1b69..f0fccd51c27b5cbe8990e625a7bdcf9972142d1f:/ldisc.c diff --git a/ldisc.c b/ldisc.c index e5727186..d57e6d17 100644 --- a/ldisc.c +++ b/ldisc.c @@ -32,13 +32,20 @@ static int plen(Ldisc ldisc, unsigned char c) return 1; else if (c < 128) return 2; /* ^x for some x */ + else if (in_utf(ldisc->term) && c >= 0xC0) + return 1; /* UTF-8 introducer character + * (FIXME: combining / wide chars) */ + else if (in_utf(ldisc->term) && c >= 0x80 && c < 0xC0) + return 0; /* UTF-8 followup character */ else - return 4; /* for hex XY */ + return 4; /* hex representation */ } static void pwrite(Ldisc ldisc, unsigned char c) { - if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(ldisc->term))) { + if ((c >= 32 && c <= 126) || + (!in_utf(ldisc->term) && c >= 0xA0) || + (in_utf(ldisc->term) && c >= 0x80)) { c_write(ldisc, (char *)&c, 1); } else if (c < 128) { char cc[2]; @@ -52,6 +59,14 @@ static void pwrite(Ldisc ldisc, unsigned char c) } } +static int char_start(Ldisc ldisc, unsigned char c) +{ + if (in_utf(ldisc->term)) + return (c < 0x80 || c >= 0xC0); + else + return 1; +} + static void bsb(Ldisc ldisc, int n) { while (n--) @@ -137,7 +152,9 @@ void ldisc_send(void *handle, char *buf, int len, int interactive) c += KCTRL('@'); switch (ldisc->quotenext ? ' ' : c) { /* - * ^h/^?: delete one char and output one BSB + * ^h/^?: delete, and output BSBs, to return to + * last character boundary (in UTF-8 mode this may + * be more than one byte) * ^w: delete, and output BSBs, to return to last * space/nonspace boundary * ^u: delete, and output BSBs, to return to BOL @@ -153,9 +170,11 @@ void ldisc_send(void *handle, char *buf, int len, int interactive) case KCTRL('H'): case KCTRL('?'): /* backspace/delete */ if (ldisc->buflen > 0) { - if (ECHOING) - bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); - ldisc->buflen--; + do { + if (ECHOING) + bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); + ldisc->buflen--; + } while (!char_start(ldisc, ldisc->buf[ldisc->buflen])); } break; case CTRL('W'): /* delete word */