1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Added local-editing line discipline to make raw backend usable

[originally from svn r287]
This commit is contained in:
Simon Tatham 1999-11-09 12:05:34 +00:00
parent b51c18f24c
commit 429b6f4a83
8 changed files with 181 additions and 14 deletions

View File

@ -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

137
ldisc.c Normal file
View File

@ -0,0 +1,137 @@
#include <windows.h>
#include <stdio.h>
#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; /* <XY> 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 };

13
putty.h
View File

@ -91,6 +91,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];
@ -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;
@ -232,6 +239,12 @@ extern Backend telnet_backend;
extern Backend ssh_backend;
/*
* Exports from ldisc.c.
*/
extern Ldisc ldisc_term, ldisc_simple;
/*
* Exports from sshrand.c.
*/

View File

@ -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;i<p-q;i++)
{
c=xlat_kbd2tty(q[i]);
back->send(&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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}