From b9d7bcadee831e9b59fb785f2464a5fc1897bd1a Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 26 Oct 2002 10:16:19 +0000 Subject: [PATCH] Line discipline module now uses dynamically allocated data. Also fixed one or two other minor problems. git-svn-id: svn://svn.tartarus.org/sgt/putty@2141 cda61777-01e9-0310-a592-d414129be87e --- console.c | 2 +- ldisc.c | 185 +++++++++++++++++++++++++++++++--------------------- plink.c | 2 +- putty.h | 11 ++-- raw.c | 6 ++ rlogin.c | 6 ++ ssh.c | 16 ++++- telnet.c | 11 +++- terminal.c | 210 ++++++++++++++++++++++++++++++++++------------------------- terminal.h | 3 + unicode.c | 10 +-- unix/pterm.c | 13 ++-- unix/pty.c | 6 ++ unix/uxucs.c | 8 +-- window.c | 39 ++++++----- winstuff.h | 2 +- 16 files changed, 326 insertions(+), 204 deletions(-) diff --git a/console.c b/console.c index 80bca3ca..85f99dc2 100644 --- a/console.c +++ b/console.c @@ -304,7 +304,7 @@ int console_get_line(const char *prompt, char *str, return 1; } -void frontend_keypress(void) +void frontend_keypress(void *handle) { /* * This is nothing but a stub, in console code. diff --git a/ldisc.c b/ldisc.c index d7b6e40a..d9335c9c 100644 --- a/ldisc.c +++ b/ldisc.c @@ -11,26 +11,33 @@ #include "putty.h" #include "terminal.h" +typedef struct ldisc_tag { + Terminal *term; + Backend *back; + void *backhandle; + void *frontend; + + char *buf; + int buflen, bufsiz, quotenext; +} *Ldisc; + #define ECHOING (cfg.localecho == LD_YES || \ (cfg.localecho == LD_BACKEND && \ - (back->ldisc(backhandle, LD_ECHO) || \ - term_ldisc(term, LD_ECHO)))) + (ldisc->back->ldisc(ldisc->backhandle, LD_ECHO) || \ + term_ldisc(ldisc->term, LD_ECHO)))) #define EDITING (cfg.localedit == LD_YES || \ (cfg.localedit == LD_BACKEND && \ - (back->ldisc(backhandle, LD_EDIT) || \ - term_ldisc(term, LD_EDIT)))) + (ldisc->back->ldisc(ldisc->backhandle, LD_EDIT) || \ + term_ldisc(ldisc->term, LD_EDIT)))) -static void c_write(char *buf, int len) +static void c_write(Ldisc ldisc, char *buf, int len) { - from_backend(term, 0, buf, len); + from_backend(ldisc->term, 0, buf, len); } -static char *term_buf = NULL; -static int term_buflen = 0, term_bufsiz = 0, term_quotenext = 0; - -static int plen(unsigned char c) +static int plen(Ldisc ldisc, unsigned char c) { - if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(term))) + if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(ldisc->term))) return 1; else if (c < 128) return 2; /* ^x for some x */ @@ -38,41 +45,66 @@ static int plen(unsigned char c) return 4; /* for hex XY */ } -static void pwrite(unsigned char c) +static void pwrite(Ldisc ldisc, unsigned char c) { - if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(term))) { - c_write(&c, 1); + if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(ldisc->term))) { + c_write(ldisc, &c, 1); } else if (c < 128) { char cc[2]; cc[1] = (c == 127 ? '?' : c + 0x40); cc[0] = '^'; - c_write(cc, 2); + c_write(ldisc, cc, 2); } else { char cc[5]; sprintf(cc, "<%02X>", c); - c_write(cc, 4); + c_write(ldisc, cc, 4); } } -static void bsb(int n) +static void bsb(Ldisc ldisc, int n) { while (n--) - c_write("\010 \010", 3); + c_write(ldisc, "\010 \010", 3); } #define CTRL(x) (x^'@') #define KCTRL(x) ((x^'@') | 0x100) -void ldisc_send(char *buf, int len, int interactive) +void *ldisc_create(Terminal *term, + Backend *back, void *backhandle, + void *frontend) { + Ldisc ldisc = smalloc(sizeof(*ldisc)); + + ldisc->buf = NULL; + ldisc->buflen = 0; + ldisc->bufsiz = 0; + ldisc->quotenext = 0; + + ldisc->back = back; + ldisc->backhandle = backhandle; + ldisc->term = term; + ldisc->frontend = frontend; + + /* Link ourselves into the backend and the terminal */ + if (term) + term->ldisc = ldisc; + if (back) + back->provide_ldisc(backhandle, ldisc); + + return ldisc; +} + +void ldisc_send(void *handle, char *buf, int len, int interactive) +{ + Ldisc ldisc = (Ldisc) handle; int keyflag = 0; /* * Called with len=0 when the options change. We must inform * the front end in case it needs to know. */ if (len == 0) { - void ldisc_update(int echo, int edit); - ldisc_update(ECHOING, EDITING); + ldisc_update(ldisc->frontend, ECHOING, EDITING); return; } /* @@ -80,7 +112,8 @@ void ldisc_send(char *buf, int len, int interactive) * it's depending on finding out (e.g. keypress termination for * Close On Exit). */ - frontend_keypress(); + frontend_keypress(ldisc->frontend); + /* * Less than zero means null terminated special string. */ @@ -97,7 +130,7 @@ void ldisc_send(char *buf, int len, int interactive) c = *buf++ + keyflag; if (!interactive && c == '\r') c += KCTRL('@'); - switch (term_quotenext ? ' ' : c) { + switch (ldisc->quotenext ? ' ' : c) { /* * ^h/^?: delete one char and output one BSB * ^w: delete, and output BSBs, to return to last @@ -114,20 +147,20 @@ void ldisc_send(char *buf, int len, int interactive) */ case KCTRL('H'): case KCTRL('?'): /* backspace/delete */ - if (term_buflen > 0) { + if (ldisc->buflen > 0) { if (ECHOING) - bsb(plen(term_buf[term_buflen - 1])); - term_buflen--; + bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); + ldisc->buflen--; } break; case CTRL('W'): /* delete word */ - while (term_buflen > 0) { + while (ldisc->buflen > 0) { if (ECHOING) - bsb(plen(term_buf[term_buflen - 1])); - term_buflen--; - if (term_buflen > 0 && - isspace(term_buf[term_buflen - 1]) && - !isspace(term_buf[term_buflen])) + 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])) break; } break; @@ -135,12 +168,12 @@ void ldisc_send(char *buf, int len, int interactive) case CTRL('C'): /* Send IP */ case CTRL('\\'): /* Quit */ case CTRL('Z'): /* Suspend */ - while (term_buflen > 0) { + while (ldisc->buflen > 0) { if (ECHOING) - bsb(plen(term_buf[term_buflen - 1])); - term_buflen--; + bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); + ldisc->buflen--; } - back->special(backhandle, TS_EL); + ldisc->back->special(ldisc->backhandle, TS_EL); /* * We don't send IP, SUSP or ABORT if the user has * configured telnet specials off! This breaks @@ -149,29 +182,29 @@ void ldisc_send(char *buf, int len, int interactive) if (!cfg.telnet_keyboard) goto default_case; if (c == CTRL('C')) - back->special(backhandle, TS_IP); + ldisc->back->special(ldisc->backhandle, TS_IP); if (c == CTRL('Z')) - back->special(backhandle, TS_SUSP); + ldisc->back->special(ldisc->backhandle, TS_SUSP); if (c == CTRL('\\')) - back->special(backhandle, TS_ABORT); + ldisc->back->special(ldisc->backhandle, TS_ABORT); break; case CTRL('R'): /* redraw line */ if (ECHOING) { int i; - c_write("^R\r\n", 4); - for (i = 0; i < term_buflen; i++) - pwrite(term_buf[i]); + c_write(ldisc, "^R\r\n", 4); + for (i = 0; i < ldisc->buflen; i++) + pwrite(ldisc, ldisc->buf[i]); } break; case CTRL('V'): /* quote next char */ - term_quotenext = TRUE; + ldisc->quotenext = TRUE; break; case CTRL('D'): /* logout or send */ - if (term_buflen == 0) { - back->special(backhandle, TS_EOF); + if (ldisc->buflen == 0) { + ldisc->back->special(ldisc->backhandle, TS_EOF); } else { - back->send(backhandle, term_buf, term_buflen); - term_buflen = 0; + ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen); + ldisc->buflen = 0; } break; /* @@ -199,81 +232,81 @@ void ldisc_send(char *buf, int len, int interactive) */ case CTRL('J'): if (cfg.protocol == PROT_RAW && - term_buflen > 0 && term_buf[term_buflen - 1] == '\r') { + ldisc->buflen > 0 && ldisc->buf[ldisc->buflen - 1] == '\r') { if (ECHOING) - bsb(plen(term_buf[term_buflen - 1])); - term_buflen--; + bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); + ldisc->buflen--; /* FALLTHROUGH */ case KCTRL('M'): /* send with newline */ - if (term_buflen > 0) - back->send(backhandle, term_buf, term_buflen); + if (ldisc->buflen > 0) + ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen); if (cfg.protocol == PROT_RAW) - back->send(backhandle, "\r\n", 2); + ldisc->back->send(ldisc->backhandle, "\r\n", 2); else if (cfg.protocol == PROT_TELNET && cfg.telnet_newline) - back->special(backhandle, TS_EOL); + ldisc->back->special(ldisc->backhandle, TS_EOL); else - back->send(backhandle, "\r", 1); + ldisc->back->send(ldisc->backhandle, "\r", 1); if (ECHOING) - c_write("\r\n", 2); - term_buflen = 0; + c_write(ldisc, "\r\n", 2); + ldisc->buflen = 0; break; } /* FALLTHROUGH */ default: /* get to this label from ^V handler */ default_case: - if (term_buflen >= term_bufsiz) { - term_bufsiz = term_buflen + 256; - term_buf = saferealloc(term_buf, term_bufsiz); + if (ldisc->buflen >= ldisc->bufsiz) { + ldisc->bufsiz = ldisc->buflen + 256; + ldisc->buf = srealloc(ldisc->buf, ldisc->bufsiz); } - term_buf[term_buflen++] = c; + ldisc->buf[ldisc->buflen++] = c; if (ECHOING) - pwrite((unsigned char) c); - term_quotenext = FALSE; + pwrite(ldisc, (unsigned char) c); + ldisc->quotenext = FALSE; break; } } } else { - if (term_buflen != 0) { - back->send(backhandle, term_buf, term_buflen); - while (term_buflen > 0) { - bsb(plen(term_buf[term_buflen - 1])); - term_buflen--; + if (ldisc->buflen != 0) { + ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen); + while (ldisc->buflen > 0) { + bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); + ldisc->buflen--; } } if (len > 0) { if (ECHOING) - c_write(buf, len); + c_write(ldisc, buf, len); if (keyflag && cfg.protocol == PROT_TELNET && len == 1) { switch (buf[0]) { case CTRL('M'): if (cfg.protocol == PROT_TELNET && cfg.telnet_newline) - back->special(backhandle, TS_EOL); + ldisc->back->special(ldisc->backhandle, TS_EOL); else - back->send(backhandle, "\r", 1); + ldisc->back->send(ldisc->backhandle, "\r", 1); break; case CTRL('?'): case CTRL('H'): if (cfg.telnet_keyboard) { - back->special(backhandle, TS_EC); + ldisc->back->special(ldisc->backhandle, TS_EC); break; } case CTRL('C'): if (cfg.telnet_keyboard) { - back->special(backhandle, TS_IP); + ldisc->back->special(ldisc->backhandle, TS_IP); break; } case CTRL('Z'): if (cfg.telnet_keyboard) { - back->special(backhandle, TS_SUSP); + ldisc->back->special(ldisc->backhandle, TS_SUSP); break; } default: - back->send(backhandle, buf, len); + ldisc->back->send(ldisc->backhandle, buf, len); break; } } else - back->send(backhandle, buf, len); + ldisc->back->send(ldisc->backhandle, buf, len); } } } diff --git a/plink.c b/plink.c index 34fe30a9..3b332642 100644 --- a/plink.c +++ b/plink.c @@ -73,7 +73,7 @@ int term_ldisc(Terminal *term, int mode) { return FALSE; } -void ldisc_update(int echo, int edit) +void ldisc_update(void *frontend, int echo, int edit) { /* Update stdin read mode to reflect changes in line discipline. */ DWORD mode; diff --git a/putty.h b/putty.h index 6c5a3ad1..3bc4a4b5 100644 --- a/putty.h +++ b/putty.h @@ -200,6 +200,7 @@ struct backend_tag { int (*exitcode) (void *handle); int (*sendok) (void *handle); int (*ldisc) (void *handle, int); + void (*provide_ldisc) (void *handle, void *ldisc); /* * back->unthrottle() tells the back end that the front end * buffer is clearing. @@ -430,7 +431,8 @@ void beep(int); void begin_session(void); void sys_cursor(int x, int y); void request_paste(void); -void frontend_keypress(void); +void frontend_keypress(void *frontend); +void ldisc_update(void *frontend, int echo, int edit); #define OPTIMISE_IS_SCROLL 1 void set_iconic(int iconic); @@ -536,7 +538,8 @@ extern Backend ssh_backend; * Exports from ldisc.c. */ -extern void ldisc_send(char *buf, int len, int interactive); +void *ldisc_create(Terminal *, Backend *, void *, void *); +void ldisc_send(void *handle, char *buf, int len, int interactive); /* * Exports from sshrand.c. @@ -566,8 +569,8 @@ extern char ver[]; #define CP_UTF8 65001 #endif void init_ucs_tables(void); -void lpage_send(int codepage, char *buf, int len, int interactive); -void luni_send(wchar_t * widebuf, int len, int interactive); +void lpage_send(void *, int codepage, char *buf, int len, int interactive); +void luni_send(void *, wchar_t * widebuf, int len, int interactive); wchar_t xlat_uskbd2cyrllic(int ch); int check_compose(int first, int second); int decode_codepage(char *cp_name); diff --git a/raw.c b/raw.c index f21e3ca9..e269a7d2 100644 --- a/raw.c +++ b/raw.c @@ -186,6 +186,11 @@ static int raw_ldisc(void *handle, int option) return 0; } +static void raw_provide_ldisc(void *handle, void *ldisc) +{ + /* This is a stub. */ +} + static int raw_exitcode(void *handle) { /* Exit codes are a meaningless concept in the Raw protocol */ @@ -202,6 +207,7 @@ Backend raw_backend = { raw_exitcode, raw_sendok, raw_ldisc, + raw_provide_ldisc, raw_unthrottle, 1 }; diff --git a/rlogin.c b/rlogin.c index 52cf356c..61f4afb8 100644 --- a/rlogin.c +++ b/rlogin.c @@ -250,6 +250,11 @@ static int rlogin_ldisc(void *handle, int option) return 0; } +static void rlogin_provide_ldisc(void *handle, void *ldisc) +{ + /* This is a stub. */ +} + static int rlogin_exitcode(void *handle) { Rlogin rlogin = (Rlogin) handle; @@ -267,6 +272,7 @@ Backend rlogin_backend = { rlogin_exitcode, rlogin_sendok, rlogin_ldisc, + rlogin_provide_ldisc, rlogin_unthrottle, 1 }; diff --git a/ssh.c b/ssh.c index 072a1b38..0a815bb6 100644 --- a/ssh.c +++ b/ssh.c @@ -555,6 +555,8 @@ struct ssh_tag { Socket s; + void *ldisc; + unsigned char session_key[32]; int v1_compressing; int v1_remote_protoflags; @@ -3233,7 +3235,8 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (ssh->eof_needed) ssh_special(ssh, TS_EOF); - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (ssh->ldisc) + ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ ssh->send_ok = 1; ssh->channels = newtree234(ssh_channelcmp); while (1) { @@ -5379,7 +5382,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Transfer data! */ - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (ssh->ldisc) + ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ ssh->send_ok = 1; while (1) { crReturnV; @@ -5854,6 +5858,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, ssh->state = SSH_STATE_PREPACKET; ssh->size_needed = FALSE; ssh->eof_needed = FALSE; + ssh->ldisc = NULL; { static const struct Packet empty = { 0, 0, NULL, NULL, 0 }; ssh->pktin = ssh->pktout = empty; @@ -6133,6 +6138,12 @@ static int ssh_ldisc(void *handle, int option) return FALSE; } +static void ssh_provide_ldisc(void *handle, void *ldisc) +{ + Ssh ssh = (Ssh) handle; + ssh->ldisc = ldisc; +} + static int ssh_return_exitcode(void *handle) { Ssh ssh = (Ssh) handle; @@ -6160,6 +6171,7 @@ Backend ssh_backend = { ssh_return_exitcode, ssh_sendok, ssh_ldisc, + ssh_provide_ldisc, ssh_unthrottle, 22 }; diff --git a/telnet.c b/telnet.c index 1a85b28e..6fcde71f 100644 --- a/telnet.c +++ b/telnet.c @@ -192,6 +192,7 @@ typedef struct telnet_tag { Socket s; void *frontend; + void *ldisc; int term_width, term_height; int opt_states[NUM_OPTS]; @@ -261,7 +262,8 @@ static void option_side_effects(Telnet telnet, const struct Opt *o, int enabled) telnet->echoing = !enabled; else if (o->option == TELOPT_SGA && o->send == DO) telnet->editing = !enabled; - ldisc_send(NULL, 0, 0); /* cause ldisc to notice the change */ + if (telnet->ldisc) /* cause ldisc to notice the change */ + ldisc_send(telnet->ldisc, NULL, 0, 0); /* Ensure we get the minimum options */ if (!telnet->activated) { @@ -908,6 +910,12 @@ static int telnet_ldisc(void *handle, int option) return FALSE; } +static void telnet_provide_ldisc(void *handle, void *ldisc) +{ + Telnet telnet = (Telnet) handle; + telnet->ldisc = ldisc; +} + static int telnet_exitcode(void *handle) { Telnet telnet = (Telnet) handle; @@ -925,6 +933,7 @@ Backend telnet_backend = { telnet_exitcode, telnet_sendok, telnet_ldisc, + telnet_provide_ldisc, telnet_unthrottle, 23 }; diff --git a/terminal.c b/terminal.c index 5a6d50a9..0cbf9182 100644 --- a/terminal.c +++ b/terminal.c @@ -241,7 +241,8 @@ void term_seen_key_event(Terminal *term) void term_pwron(Terminal *term) { power_on(term); - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (term->ldisc) /* cause ldisc to notice changes */ + ldisc_send(term->ldisc, NULL, 0, 0); fix_cpos; term->disptop = 0; deselect(term); @@ -309,7 +310,7 @@ Terminal *term_init(void) term->vt52_mode = FALSE; term->cr_lf_return = FALSE; term->seen_disp_event = FALSE; - term->xterm_mouse = FALSE; + term->xterm_mouse = term->mouse_is_down = FALSE; term->reset_132 = FALSE; term->blinker = term->tblinker = 0; term->has_focus = 1; @@ -915,7 +916,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state) break; case 10: /* set local edit mode */ term->term_editing = state; - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (term->ldisc) /* cause ldisc to notice changes */ + ldisc_send(term->ldisc, NULL, 0, 0); break; case 25: /* enable/disable cursor */ compatibility2(OTHER, VT220); @@ -965,7 +967,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state) break; case 12: /* set echo mode */ term->term_echoing = !state; - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (term->ldisc) /* cause ldisc to notice changes */ + ldisc_send(term->ldisc, NULL, 0, 0); break; case 20: /* Return sends ... */ term->cr_lf_return = state; @@ -1288,7 +1291,7 @@ void term_out(Terminal *term) * An xterm returns "xterm" (5 characters) */ compatibility(ANSIMIN); - { + if (term->ldisc) { char abuf[256], *s, *d; int state = 0; for (s = cfg.answerback, d = abuf; *s; s++) { @@ -1306,7 +1309,8 @@ void term_out(Terminal *term) } else *d++ = *s; } - lpage_send(DEFAULT_CODEPAGE, abuf, d - abuf, 0); + lpage_send(term->ldisc, DEFAULT_CODEPAGE, + abuf, d - abuf, 0); } break; case '\007': @@ -1617,12 +1621,15 @@ void term_out(Terminal *term) break; case 'Z': /* terminal type query */ compatibility(VT100); - ldisc_send(term->id_string, strlen(term->id_string), 0); + if (term->ldisc) + ldisc_send(term->ldisc, term->id_string, + strlen(term->id_string), 0); break; case 'c': /* restore power-on settings */ compatibility(VT100); power_on(term); - ldisc_send(NULL, 0, 0);/* cause ldisc to notice changes */ + if (term->ldisc) /* cause ldisc to notice changes */ + ldisc_send(term->ldisc, NULL, 0, 0); if (term->reset_132) { if (!cfg.no_remote_resize) request_resize(80, term->rows); @@ -1783,7 +1790,8 @@ void term_out(Terminal *term) compatibility(OTHER); /* this reports xterm version 136 so that VIM can use the drag messages from the mouse reporting */ - ldisc_send("\033[>0;136;0c", 11, 0); + if (term->ldisc) + ldisc_send(term->ldisc, "\033[>0;136;0c", 11, 0); break; case 'a': /* move right N cols */ compatibility(ANSI); @@ -1885,17 +1893,20 @@ void term_out(Terminal *term) case 'c': /* terminal type query */ compatibility(VT100); /* This is the response for a VT102 */ - ldisc_send(term->id_string, - strlen(term->id_string), 0); + if (term->ldisc) + ldisc_send(term->ldisc, term->id_string, + strlen(term->id_string), 0); break; case 'n': /* cursor position query */ - if (term->esc_args[0] == 6) { - char buf[32]; - sprintf(buf, "\033[%d;%dR", term->curs.y + 1, - term->curs.x + 1); - ldisc_send(buf, strlen(buf), 0); - } else if (term->esc_args[0] == 5) { - ldisc_send("\033[0n", 4, 0); + if (term->ldisc) { + if (term->esc_args[0] == 6) { + char buf[32]; + sprintf(buf, "\033[%d;%dR", term->curs.y + 1, + term->curs.x + 1); + ldisc_send(term->ldisc, buf, strlen(buf), 0); + } else if (term->esc_args[0] == 5) { + ldisc_send(term->ldisc, "\033[0n", 4, 0); + } } break; case 'h': /* toggle modes to high */ @@ -2175,23 +2186,31 @@ void term_out(Terminal *term) TRUE : FALSE); break; case 11: - ldisc_send(is_iconic() ? "\033[1t" : "\033[2t", - 4, 0); + if (term->ldisc) + ldisc_send(term->ldisc, + is_iconic() ? "\033[1t" : + "\033[2t", 4, 0); break; case 13: - get_window_pos(&x, &y); - len = sprintf(buf, "\033[3;%d;%dt", x, y); - ldisc_send(buf, len, 0); + if (term->ldisc) { + get_window_pos(&x, &y); + len = sprintf(buf, "\033[3;%d;%dt", x, y); + ldisc_send(term->ldisc, buf, len, 0); + } break; case 14: - get_window_pixels(&x, &y); - len = sprintf(buf, "\033[4;%d;%dt", x, y); - ldisc_send(buf, len, 0); + if (term->ldisc) { + get_window_pixels(&x, &y); + len = sprintf(buf, "\033[4;%d;%dt", x, y); + ldisc_send(term->ldisc, buf, len, 0); + } break; case 18: - len = sprintf(buf, "\033[8;%d;%dt", - term->rows, term->cols); - ldisc_send(buf, len, 0); + if (term->ldisc) { + len = sprintf(buf, "\033[8;%d;%dt", + term->rows, term->cols); + ldisc_send(term->ldisc, buf, len, 0); + } break; case 19: /* @@ -2211,18 +2230,22 @@ void term_out(Terminal *term) */ break; case 20: - p = get_window_title(TRUE); - len = strlen(p); - ldisc_send("\033]L", 3, 0); - ldisc_send(p, len, 0); - ldisc_send("\033\\", 2, 0); + if (term->ldisc) { + p = get_window_title(TRUE); + len = strlen(p); + ldisc_send(term->ldisc, "\033]L", 3, 0); + ldisc_send(term->ldisc, p, len, 0); + ldisc_send(term->ldisc, "\033\\", 2, 0); + } break; case 21: - p = get_window_title(FALSE); - len = strlen(p); - ldisc_send("\033]l", 3, 0); - ldisc_send(p, len, 0); - ldisc_send("\033\\", 2, 0); + if (term->ldisc) { + p = get_window_title(FALSE); + len = strlen(p); + ldisc_send(term->ldisc, "\033]l", 3, 0); + ldisc_send(term->ldisc, p, len, 0); + ldisc_send(term->ldisc, "\033\\", 2, 0); + } break; } } @@ -2290,13 +2313,13 @@ void term_out(Terminal *term) break; case 'x': /* report terminal characteristics */ compatibility(VT100); - { + if (term->ldisc) { char buf[32]; int i = def(term->esc_args[0], 0); if (i == 0 || i == 1) { strcpy(buf, "\033[2;1;1;112;112;1;0x"); buf[2] += i; - ldisc_send(buf, 20, 0); + ldisc_send(term->ldisc, buf, 20, 0); } } break; @@ -2620,7 +2643,8 @@ void term_out(Terminal *term) term->termstate = VT52_Y1; break; case 'Z': - ldisc_send("\033/Z", 3, 0); + if (term->ldisc) + ldisc_send(term->ldisc, "\033/Z", 3, 0); break; case '=': term->app_keypad_keys = TRUE; @@ -3281,9 +3305,10 @@ void term_copyall(Terminal *term) */ static int wordtype(Terminal *term, int uc) { - static struct { + struct ucsword { int start, end, ctype; - } *wptr, ucs_words[] = { + }; + static const struct ucsword ucs_words[] = { { 128, 160, 0}, { 161, 191, 1}, { @@ -3347,6 +3372,7 @@ static int wordtype(Terminal *term, int uc) { 0, 0, 0} }; + const struct ucsword *wptr; uc &= (CSET_MASK | CHAR_MASK); @@ -3524,7 +3550,8 @@ void term_do_paste(Terminal *term) /* Assume a small paste will be OK in one go. */ if (term->paste_len < 256) { - luni_send(term->paste_buffer, term->paste_len, 0); + if (term->ldisc) + luni_send(term->ldisc, term->paste_buffer, term->paste_len, 0); if (term->paste_buffer) sfree(term->paste_buffer); term->paste_buffer = 0; @@ -3573,52 +3600,54 @@ void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y, if (raw_mouse) { int encstate = 0, r, c; char abuf[16]; - static int is_down = 0; - switch (b) { - case MBT_LEFT: - encstate = 0x20; /* left button down */ - break; - case MBT_MIDDLE: - encstate = 0x21; - break; - case MBT_RIGHT: - encstate = 0x22; - break; - case MBT_WHEEL_UP: - encstate = 0x60; - break; - case MBT_WHEEL_DOWN: - encstate = 0x61; - break; - default: break; /* placate gcc warning about enum use */ - } - switch (a) { - case MA_DRAG: - if (term->xterm_mouse == 1) - return; - encstate += 0x20; - break; - case MA_RELEASE: - encstate = 0x23; - is_down = 0; - break; - case MA_CLICK: - if (is_down == b) - return; - is_down = b; - break; - default: break; /* placate gcc warning about enum use */ + if (term->ldisc) { + + switch (b) { + case MBT_LEFT: + encstate = 0x20; /* left button down */ + break; + case MBT_MIDDLE: + encstate = 0x21; + break; + case MBT_RIGHT: + encstate = 0x22; + break; + case MBT_WHEEL_UP: + encstate = 0x60; + break; + case MBT_WHEEL_DOWN: + encstate = 0x61; + break; + default: break; /* placate gcc warning about enum use */ + } + switch (a) { + case MA_DRAG: + if (term->xterm_mouse == 1) + return; + encstate += 0x20; + break; + case MA_RELEASE: + encstate = 0x23; + term->mouse_is_down = 0; + break; + case MA_CLICK: + if (term->mouse_is_down == b) + return; + term->mouse_is_down = b; + break; + default: break; /* placate gcc warning about enum use */ + } + if (shift) + encstate += 0x04; + if (ctrl) + encstate += 0x10; + r = y + 33; + c = x + 33; + + sprintf(abuf, "\033[M%c%c%c", encstate, c, r); + ldisc_send(term->ldisc, abuf, 6, 0); } - if (shift) - encstate += 0x04; - if (ctrl) - encstate += 0x10; - r = y + 33; - c = x + 33; - - sprintf(abuf, "\033[M%c%c%c", encstate, c, r); - ldisc_send(abuf, 6, 0); return; } @@ -3775,7 +3804,8 @@ void term_paste(Terminal *term) if (term->paste_buffer[term->paste_pos + n++] == '\r') break; } - luni_send(term->paste_buffer + term->paste_pos, n, 0); + if (term->ldisc) + luni_send(term->ldisc, term->paste_buffer + term->paste_pos, n, 0); term->paste_pos += n; if (term->paste_pos < term->paste_len) { diff --git a/terminal.h b/terminal.h index 792f89b4..9628e07f 100644 --- a/terminal.h +++ b/terminal.h @@ -94,6 +94,7 @@ struct terminal_tag { long last_tblink; int xterm_mouse; /* send mouse messages to app */ + int mouse_is_down; /* used while tracking mouse buttons */ unsigned long cset_attr[2]; @@ -160,6 +161,8 @@ struct terminal_tag { void (*resize_fn)(void *, int, int); void *resize_ctx; + + void *ldisc; }; #define in_utf(term) ((term)->utf || line_codepage==CP_UTF8) diff --git a/unicode.c b/unicode.c index 182e2443..19a2e1d2 100644 --- a/unicode.c +++ b/unicode.c @@ -598,14 +598,14 @@ static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr) } } -void lpage_send(int codepage, char *buf, int len, int interactive) +void lpage_send(void *ldisc, int codepage, char *buf, int len, int interactive) { static wchar_t *widebuffer = 0; static int widesize = 0; int wclen; if (codepage < 0) { - ldisc_send(buf, len, interactive); + ldisc_send(ldisc, buf, len, interactive); return; } @@ -616,10 +616,10 @@ void lpage_send(int codepage, char *buf, int len, int interactive) } wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize); - luni_send(widebuffer, wclen, interactive); + luni_send(ldisc, widebuffer, wclen, interactive); } -void luni_send(wchar_t * widebuf, int len, int interactive) +void luni_send(void *ldisc, wchar_t * widebuf, int len, int interactive) { static char *linebuffer = 0; static int linesize = 0; @@ -677,7 +677,7 @@ void luni_send(wchar_t * widebuf, int len, int interactive) } } if (p > linebuffer) - ldisc_send(linebuffer, p - linebuffer, interactive); + ldisc_send(ldisc, linebuffer, p - linebuffer, interactive); } wchar_t xlat_uskbd2cyrllic(int ch) diff --git a/unix/pterm.c b/unix/pterm.c index 53ca4428..2791693a 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -53,13 +53,14 @@ struct gui_data { char wintitle[sizeof(((Config *)0)->wintitle)]; char icontitle[sizeof(((Config *)0)->wintitle)]; int master_fd, master_func_id, exited; + void *ldisc; }; static struct gui_data the_inst; static struct gui_data *inst = &the_inst; /* so we always write `inst->' */ static int send_raw_mouse; -void ldisc_update(int echo, int edit) +void ldisc_update(void *frontend, int echo, int edit) { /* * This is a stub in pterm. If I ever produce a Unix @@ -792,7 +793,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) printf("\n"); #endif - ldisc_send(output+start, end-start, 1); + ldisc_send(inst->ldisc, output+start, end-start, 1); show_mouseptr(0); term_seen_key_event(term); term_out(term); @@ -924,8 +925,10 @@ void done_with_pty(struct gui_data *inst) } } -void frontend_keypress(void) +void frontend_keypress(void *handle) { + struct gui_data *inst = (struct gui_data *)handle; + /* * If our child process has exited but not closed, terminate on * any keypress. @@ -1965,7 +1968,9 @@ int main(int argc, char **argv) term_provide_resize_fn(term, back->size, backhandle); term_size(term, cfg.height, cfg.width, cfg.savelines); - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + + inst->ldisc = ldisc_create(term, back, backhandle, inst); + ldisc_send(inst->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ inst->master_fd = pty_master_fd; inst->exited = FALSE; diff --git a/unix/pty.c b/unix/pty.c index 44348a3e..67addceb 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -589,6 +589,11 @@ static int pty_ldisc(void *handle, int option) return 0; /* neither editing nor echoing */ } +static void pty_provide_ldisc(void *handle, void *ldisc) +{ + /* This is a stub. */ +} + static int pty_exitcode(void *handle) { if (!pty_child_dead) @@ -607,6 +612,7 @@ Backend pty_backend = { pty_exitcode, pty_sendok, pty_ldisc, + pty_provide_ldisc, pty_unthrottle, 1 }; diff --git a/unix/uxucs.c b/unix/uxucs.c index 78d196f1..ff8f3a1c 100644 --- a/unix/uxucs.c +++ b/unix/uxucs.c @@ -14,12 +14,12 @@ * are ISO8859-1. */ -void lpage_send(int codepage, char *buf, int len, int interactive) +void lpage_send(void *ldisc, int codepage, char *buf, int len, int interactive) { - ldisc_send(buf, len, interactive); + ldisc_send(ldisc, buf, len, interactive); } -void luni_send(wchar_t * widebuf, int len, int interactive) +void luni_send(void *ldisc, wchar_t * widebuf, int len, int interactive) { static char *linebuffer = 0; static int linesize = 0; @@ -79,7 +79,7 @@ void luni_send(wchar_t * widebuf, int len, int interactive) } } if (p > linebuffer) - ldisc_send(linebuffer, p - linebuffer, interactive); + ldisc_send(ldisc, linebuffer, p - linebuffer, interactive); } int is_dbcs_leadbyte(int codepage, char byte) diff --git a/window.c b/window.c index 0171d521..c53395a2 100644 --- a/window.c +++ b/window.c @@ -108,12 +108,15 @@ static LPARAM pend_netevent_lParam = 0; static void enact_pending_netevent(void); static void flash_window(int mode); static void sys_cursor_update(void); +static int is_shift_pressed(void); static int get_fullscreen_rect(RECT * ss); static time_t last_movement = 0; static int caret_x = -1, caret_y = -1; +static void *ldisc; + #define FONT_NORMAL 0 #define FONT_BOLD 1 #define FONT_UNDERLINE 2 @@ -168,7 +171,7 @@ static OSVERSIONINFO osVersion; static UINT wm_mousewheel = WM_MOUSEWHEEL; /* Dummy routine, only required in plink. */ -void ldisc_update(int echo, int edit) +void ldisc_update(void *frontend, int echo, int edit) { } @@ -625,6 +628,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) */ term_provide_resize_fn(term, back->size, backhandle); + /* + * Set up a line discipline. + */ + ldisc = ldisc_create(term, back, backhandle, NULL); + session_closed = FALSE; /* @@ -1748,7 +1756,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * Flush the line discipline's edit buffer in the * case where local editing has just been disabled. */ - ldisc_send(NULL, 0, 0); + ldisc_send(ldisc, NULL, 0, 0); if (pal) DeleteObject(pal); logpal = NULL; @@ -1862,7 +1870,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, break; case IDM_RESET: term_pwron(term); - ldisc_send(NULL, 0, 0); + ldisc_send(ldisc, NULL, 0, 0); break; case IDM_TEL_AYT: back->special(backhandle, TS_AYT); @@ -2450,7 +2458,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * we're sent. */ term_seen_key_event(term); - ldisc_send(buf, len, 1); + ldisc_send(ldisc, buf, len, 1); show_mouseptr(0); } } @@ -2498,7 +2506,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, */ term_seen_key_event(term); for (i = 0; i < n; i += 2) { - luni_send((unsigned short *)(buff+i), 1, 1); + luni_send(ldisc, (unsigned short *)(buff+i), 1, 1); } free(buff); } @@ -2513,11 +2521,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, buf[1] = wParam; buf[0] = wParam >> 8; term_seen_key_event(term); - lpage_send(kbd_codepage, buf, 2, 1); + lpage_send(ldisc, kbd_codepage, buf, 2, 1); } else { char c = (unsigned char) wParam; term_seen_key_event(term); - lpage_send(kbd_codepage, &c, 1, 1); + lpage_send(ldisc, kbd_codepage, &c, 1, 1); } return (0); case WM_CHAR: @@ -2531,7 +2539,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, { char c = (unsigned char)wParam; term_seen_key_event(term); - lpage_send(CP_ACP, &c, 1, 1); + lpage_send(ldisc, CP_ACP, &c, 1, 1); } return 0; case WM_SETCURSOR: @@ -3780,7 +3788,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, } keybuf = nc; term_seen_key_event(term); - luni_send(&keybuf, 1, 1); + luni_send(ldisc, &keybuf, 1, 1); continue; } @@ -3791,7 +3799,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, if (in_utf(term) || dbcs_screenfont) { keybuf = alt_sum; term_seen_key_event(term); - luni_send(&keybuf, 1, 1); + luni_send(ldisc, &keybuf, 1, 1); } else { ch = (char) alt_sum; /* @@ -3804,25 +3812,26 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, * everything we're sent. */ term_seen_key_event(term); - ldisc_send(&ch, 1, 1); + ldisc_send(ldisc, &ch, 1, 1); } alt_sum = 0; } else term_seen_key_event(term); - lpage_send(kbd_codepage, &ch, 1, 1); + lpage_send(ldisc, kbd_codepage, &ch, 1, 1); } else { if(capsOn && ch < 0x80) { WCHAR cbuf[2]; cbuf[0] = 27; cbuf[1] = xlat_uskbd2cyrllic(ch); term_seen_key_event(term); - luni_send(cbuf+!left_alt, 1+!!left_alt, 1); + luni_send(ldisc, cbuf+!left_alt, 1+!!left_alt, 1); } else { char cbuf[2]; cbuf[0] = '\033'; cbuf[1] = ch; term_seen_key_event(term); - lpage_send(kbd_codepage, cbuf+!left_alt, 1+!!left_alt, 1); + lpage_send(ldisc, kbd_codepage, + cbuf+!left_alt, 1+!!left_alt, 1); } } show_mouseptr(0); @@ -4559,7 +4568,7 @@ void flip_full_screen() } } -void frontend_keypress(void) +void frontend_keypress(void *handle) { /* * Keypress termination in non-Close-On-Exit mode is not diff --git a/winstuff.h b/winstuff.h index dadce6e0..5ce7387e 100644 --- a/winstuff.h +++ b/winstuff.h @@ -174,6 +174,6 @@ void EnableSizeTip(int bEnable); #define mb_to_wc(cp, flags, mbstr, mblen, wcstr, wclen) \ MultiByteToWideChar(cp, flags, mbstr, mblen, wcstr, wclen) #define wc_to_mb(cp, flags, wcstr, wclen, mbstr, mblen, def, defused) \ - WideCharToMultiByte(cp, flags, mbstr, mblen, wcstr, wclen, def,defused) + WideCharToMultiByte(cp, flags, wcstr, wclen, mbstr, mblen, def,defused) #endif -- 2.11.0