X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/fe5634f616c5bf0afdf883045dc309e82c6ac41c..976374cdc06f5adb4217cb816f9bfe928d0809e6:/ldisc.c diff --git a/ldisc.c b/ldisc.c index c77b5c8f..d57e6d17 100644 --- a/ldisc.c +++ b/ldisc.c @@ -12,18 +12,18 @@ #include "terminal.h" #include "ldisc.h" -#define ECHOING (ldisc->cfg->localecho == LD_YES || \ - (ldisc->cfg->localecho == LD_BACKEND && \ +#define ECHOING (ldisc->cfg->localecho == FORCE_ON || \ + (ldisc->cfg->localecho == AUTO && \ (ldisc->back->ldisc(ldisc->backhandle, LD_ECHO) || \ term_ldisc(ldisc->term, LD_ECHO)))) -#define EDITING (ldisc->cfg->localedit == LD_YES || \ - (ldisc->cfg->localedit == LD_BACKEND && \ +#define EDITING (ldisc->cfg->localedit == FORCE_ON || \ + (ldisc->cfg->localedit == AUTO && \ (ldisc->back->ldisc(ldisc->backhandle, LD_EDIT) || \ term_ldisc(ldisc->term, LD_EDIT)))) static void c_write(Ldisc ldisc, char *buf, int len) { - from_backend(ldisc->term, 0, buf, len); + from_backend(ldisc->frontend, 0, buf, len); } static int plen(Ldisc ldisc, unsigned char 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--) @@ -65,7 +80,7 @@ void *ldisc_create(Config *mycfg, Terminal *term, Backend *back, void *backhandle, void *frontend) { - Ldisc ldisc = smalloc(sizeof(*ldisc)); + Ldisc ldisc = snew(struct ldisc_tag); ldisc->buf = NULL; ldisc->buflen = 0; @@ -87,6 +102,19 @@ void *ldisc_create(Config *mycfg, Terminal *term, return ldisc; } +void ldisc_free(void *handle) +{ + Ldisc ldisc = (Ldisc) handle; + + if (ldisc->term) + ldisc->term->ldisc = NULL; + if (ldisc->back) + ldisc->back->provide_ldisc(ldisc->backhandle, NULL); + if (ldisc->buf) + sfree(ldisc->buf); + sfree(ldisc); +} + void ldisc_send(void *handle, char *buf, int len, int interactive) { Ldisc ldisc = (Ldisc) handle; @@ -124,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 @@ -140,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 */ @@ -151,8 +183,8 @@ void ldisc_send(void *handle, char *buf, int len, int interactive) bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); ldisc->buflen--; if (ldisc->buflen > 0 && - isspace(ldisc->buf[ldisc->buflen - 1]) && - !isspace(ldisc->buf[ldisc->buflen])) + isspace((unsigned char)ldisc->buf[ldisc->buflen-1]) && + !isspace((unsigned char)ldisc->buf[ldisc->buflen])) break; } break; @@ -248,7 +280,7 @@ void ldisc_send(void *handle, char *buf, int len, int interactive) default_case: if (ldisc->buflen >= ldisc->bufsiz) { ldisc->bufsiz = ldisc->buflen + 256; - ldisc->buf = srealloc(ldisc->buf, ldisc->bufsiz); + ldisc->buf = sresize(ldisc->buf, ldisc->bufsiz, char); } ldisc->buf[ldisc->buflen++] = c; if (ECHOING)