From: simon Date: Tue, 9 Nov 1999 12:05:34 +0000 (+0000) Subject: Added local-editing line discipline to make raw backend usable X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/commitdiff_plain/5bc238bbefc16c6d86a914aa5baa51d34acb20b3?hp=8ce72d2c1c7651def2425be607ef623e6b0b9bd2 Added local-editing line discipline to make raw backend usable git-svn-id: svn://svn.tartarus.org/sgt/putty@287 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/Makefile b/Makefile index 2f263192..00157caa 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,8 @@ CFLAGS = /nologo /W3 /YX /O2 /Yd /D_WINDOWS /DDEBUG /ML /Fd .c.obj: cl $(COMPAT) $(FWHACK) $(CFLAGS) /c $*.c -PUTTYOBJS = window.obj windlg.obj terminal.obj telnet.obj raw.obj xlat.obj +POBJS1 = window.obj windlg.obj terminal.obj telnet.obj raw.obj +POBJS2 = xlat.obj ldisc.obj OBJS1 = misc.obj noise.obj OBJS2 = ssh.obj sshcrc.obj sshdes.obj sshmd5.obj sshrsa.obj sshrand.obj OBJS3 = sshsha.obj sshblowf.obj version.obj sizetip.obj @@ -26,15 +27,16 @@ SCPOBJS3 = sshrsa.obj sshrand.obj sshsha.obj sshblowf.obj version.obj all: putty.exe pscp.exe -putty.exe: $(PUTTYOBJS) $(OBJS1) $(OBJS2) $(OBJS3) $(RESRC) link.rsp +putty.exe: $(POBJS1) $(POBJS2) $(OBJS1) $(OBJS2) $(OBJS3) $(RESRC) link.rsp link /debug -out:putty.exe @link.rsp -puttyd.exe: $(PUTTYOBJS) $(OBJS1) $(OBJS2) $(OBJS3) $(RESRC) link.rsp +puttyd.exe: $(POBJS1) $(POBJS2) $(OBJS1) $(OBJS2) $(OBJS3) $(RESRC) link.rsp link /debug -out:puttyd.exe @link.rsp link.rsp: makefile echo /nologo /subsystem:windows > link.rsp - echo $(PUTTYOBJS) >> link.rsp + echo $(POBJS1) >> link.rsp + echo $(POBJS2) >> link.rsp echo $(OBJS1) >> link.rsp echo $(OBJS2) >> link.rsp echo $(OBJS3) >> link.rsp @@ -49,6 +51,7 @@ sizetip.obj: sizetip.c putty.h telnet.obj: telnet.c putty.h raw.obj: raw.c putty.h xlat.obj: xlat.c putty.h +ldisc.obj: ldisc.c putty.h misc.obj: misc.c putty.h noise.obj: noise.c putty.h ssh.h ssh.obj: ssh.c ssh.h putty.h diff --git a/ldisc.c b/ldisc.c new file mode 100644 index 00000000..cb2764ef --- /dev/null +++ b/ldisc.c @@ -0,0 +1,137 @@ +#include +#include + +#include "putty.h" + +/* + * ldisc.c: PuTTY line disciplines + */ + +static void c_write (char *buf, int len) { + while (len--) { + int new_head = (inbuf_head + 1) & INBUF_MASK; + int c = (unsigned char) *buf; + if (new_head != inbuf_reap) { + inbuf[inbuf_head] = *buf++; + inbuf_head = new_head; + } + } +} + +static char *term_buf = NULL; +static int term_buflen = 0, term_bufsiz = 0, term_quotenext = 0; + +static int plen(unsigned char c) { + if ((c >= 32 && c <= 126) || + (c >= 160)) + return 1; + else if (c < 128) + return 2; /* ^x for some x */ + else + return 4; /* for hex XY */ +} + +static void pwrite(unsigned char c) { + if ((c >= 32 && c <= 126) || + (c >= 160)) { + char cc = (char)c; + c_write(&cc, 1); + } else if (c < 128) { + char cc[2]; + cc[1] = (c == 127 ? '?' : c + 0x40); + cc[0] = '^'; + c_write(cc, 2); + } else { + char cc[5]; + sprintf(cc, "<%02X>", c); + c_write(cc, 4); + } +} + +static void bsb(int n) { + while (n--) + c_write("\010 \010", 3); +} + +static void term_send(char *buf, int len) { + while (len--) { + char c; + c = *buf++; + switch (term_quotenext ? ' ' : c) { + /* + * ^h/^?: delete one char and output one BSB + * ^w: delete, and output BSBs, to return to last space/nonspace + * boundary + * ^u: delete, and output BSBs, to return to BOL + * ^r: echo "^R\n" and redraw line + * ^v: quote next char + * ^d: if at BOL, end of file and close connection, else send line + * and reset to BOL + * ^m/^j: send line-plus-\r\n and reset to BOL + */ + case 8: case 127: /* backspace/delete */ + if (term_buflen > 0) { + bsb(plen(term_buf[term_buflen-1])); + term_buflen--; + } + break; + case 23: /* ^W delete word */ + while (term_buflen > 0) { + bsb(plen(term_buf[term_buflen-1])); + term_buflen--; + if (term_buflen > 0 && + isspace(term_buf[term_buflen-1]) && + !isspace(term_buf[term_buflen])) + break; + } + break; + case 21: /* ^U delete line */ + while (term_buflen > 0) { + bsb(plen(term_buf[term_buflen-1])); + term_buflen--; + } + break; + case 18: /* ^R redraw line */ + c_write("^R\r\n", 4); + { + int i; + for (i = 0; i < term_buflen; i++) + pwrite(term_buf[i]); + } + break; + case 22: /* ^V quote next char */ + term_quotenext = TRUE; + break; + case 4: /* ^D logout or send */ + if (term_buflen == 0) { + /* FIXME: eof */; + } else { + back->send(term_buf, term_buflen); + term_buflen = 0; + } + break; + case 13: case 10: /* ^M/^J send with newline */ + back->send(term_buf, term_buflen); + back->send("\r\n", 2); + c_write("\r\n", 2); + term_buflen = 0; + break; + default: /* get to this label from ^V handler */ + if (term_buflen >= term_bufsiz) { + term_bufsiz = term_buflen + 256; + term_buf = saferealloc(term_buf, term_bufsiz); + } + term_buf[term_buflen++] = c; + pwrite(c); + term_quotenext = FALSE; + break; + } + } +} + +static void simple_send(char *buf, int len) { + back->send(buf, len); +} + +Ldisc ldisc_term = { term_send }; +Ldisc ldisc_simple = { simple_send }; diff --git a/putty.h b/putty.h index e5744eab..abbb9121 100644 --- a/putty.h +++ b/putty.h @@ -92,6 +92,12 @@ typedef struct { GLOBAL Backend *back; typedef struct { + void (*send) (char *buf, int len); +} Ldisc; + +GLOBAL Ldisc *ldisc; + +typedef struct { /* Basic options */ char host[512]; int port; @@ -117,6 +123,7 @@ typedef struct { int nethack_keypad; int alt_f4; /* is it special? */ int alt_space; /* is it special? */ + int ldisc_term; /* Terminal options */ int savelines; int dec_om; @@ -233,6 +240,12 @@ extern Backend telnet_backend; extern Backend ssh_backend; /* + * Exports from ldisc.c. + */ + +extern Ldisc ldisc_term, ldisc_simple; + +/* * Exports from sshrand.c. */ diff --git a/terminal.c b/terminal.c index f4669df4..0218c098 100644 --- a/terminal.c +++ b/terminal.c @@ -577,7 +577,7 @@ void term_out(void) { do_toplevel: switch (c) { case '\005': /* terminal type query */ - back->send ("\033[?1;2c", 7); + ldisc->send ("\033[?1;2c", 7); break; case '\007': beep(); @@ -766,7 +766,7 @@ void term_out(void) { must_update = TRUE; break; case 'Z': /* terminal type query */ - back->send ("\033[?6c", 5); + ldisc->send ("\033[?6c", 5); break; case 'c': /* restore power-on settings */ power_on(); @@ -902,13 +902,13 @@ void term_out(void) { must_update = TRUE; break; case 'c': /* terminal type query */ - back->send ("\033[?6c", 5); + ldisc->send ("\033[?6c", 5); break; case 'n': /* cursor position query */ if (esc_args[0] == 6) { char buf[32]; sprintf (buf, "\033[%d;%dR", curs_y + 1, curs_x + 1); - back->send (buf, strlen(buf)); + ldisc->send (buf, strlen(buf)); } break; case 'h': /* toggle a mode to high */ @@ -1031,7 +1031,7 @@ void term_out(void) { if (i == 0 || i == 1) { strcpy (buf, "\033[2;1;1;112;112;1;0x"); buf[2] += i; - back->send (buf, 20); + ldisc->send (buf, 20); } } break; @@ -1443,13 +1443,13 @@ void term_mouse (Mouse_Button b, Mouse_Action a, int x, int y) { for(i=0;isend(&c,1); + ldisc->send(&c,1); } } if (p <= data+len-sizeof(sel_nl) && !memcmp(p, sel_nl, sizeof(sel_nl))) { - back->send ("\r", 1); + ldisc->send ("\r", 1); p += sizeof(sel_nl); } q = p; diff --git a/win_res.h b/win_res.h index aec42f63..4d6446e6 100644 --- a/win_res.h +++ b/win_res.h @@ -63,6 +63,7 @@ #define IDC1_CURAPPLIC 1016 #define IDC1_ALTF4 1017 #define IDC1_ALTSPACE 1018 +#define IDC1_LDISCTERM 1019 #define IDC2_WRAPMODE 1001 #define IDC2_DECOM 1002 diff --git a/win_res.rc b/win_res.rc index 37b5eca0..c1f8094f 100644 --- a/win_res.rc +++ b/win_res.rc @@ -105,6 +105,8 @@ BEGIN IDC1_ALTF4, 3, 113, 162, 10 AUTOCHECKBOX "ALT-Space is special (S&ystem menu)", IDC1_ALTSPACE, 3, 123, 162, 10 + AUTOCHECKBOX "&Use local terminal line discipline", + IDC1_LDISCTERM, 3, 133, 162, 10 END IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163 diff --git a/windlg.c b/windlg.c index 69f91fb9..0a8f8009 100644 --- a/windlg.c +++ b/windlg.c @@ -157,6 +157,7 @@ static void save_settings (char *section, int do_host) { wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad); wppi (sesskey, "AltF4", cfg.alt_f4); wppi (sesskey, "AltSpace", cfg.alt_space); + wppi (sesskey, "LdiscTerm", cfg.ldisc_term); wppi (sesskey, "ScrollbackLines", cfg.savelines); wppi (sesskey, "DECOriginMode", cfg.dec_om); wppi (sesskey, "AutoWrapMode", cfg.wrap_mode); @@ -290,6 +291,7 @@ static void load_settings (char *section, int do_host) { gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad); gppi (sesskey, "AltF4", 1, &cfg.alt_f4); gppi (sesskey, "AltSpace", 0, &cfg.alt_space); + gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term); gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines); gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om); gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode); @@ -636,6 +638,7 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg, cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL); CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4); CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space); + CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term); break; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED || @@ -676,6 +679,11 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg, HIWORD(wParam) == BN_DOUBLECLICKED) cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE); break; + case IDC1_LDISCTERM: + if (HIWORD(wParam) == BN_CLICKED || + HIWORD(wParam) == BN_DOUBLECLICKED) + cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM); + break; } } return GeneralPanelProc (hwnd, msg, wParam, lParam); diff --git a/window.c b/window.c index dd1365ce..a636ac5d 100644 --- a/window.c +++ b/window.c @@ -181,7 +181,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { } back = (cfg.protocol == PROT_SSH ? &ssh_backend : - cfg.protocol == PROT_TELNET ? &telnet_backend : &raw_backend ); + cfg.protocol == PROT_TELNET ? &telnet_backend : + &raw_backend); + + ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple); if (!prev) { wndclass.style = 0; @@ -1016,7 +1019,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message, len = TranslateKey (wParam, lParam, buf); if (len == -1) return DefWindowProc (hwnd, message, wParam, lParam); - back->send (buf, len); + ldisc->send (buf, len); } return 0; case WM_KEYUP: @@ -1056,7 +1059,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message, */ { char c = xlat_kbd2tty((unsigned char)wParam); - back->send (&c, 1); + ldisc->send (&c, 1); } return 0; }