mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
Added local-editing line discipline to make raw backend usable
[originally from svn r287]
This commit is contained in:
parent
b51c18f24c
commit
429b6f4a83
11
Makefile
11
Makefile
@ -13,7 +13,8 @@ CFLAGS = /nologo /W3 /YX /O2 /Yd /D_WINDOWS /DDEBUG /ML /Fd
|
|||||||
.c.obj:
|
.c.obj:
|
||||||
cl $(COMPAT) $(FWHACK) $(CFLAGS) /c $*.c
|
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
|
OBJS1 = misc.obj noise.obj
|
||||||
OBJS2 = ssh.obj sshcrc.obj sshdes.obj sshmd5.obj sshrsa.obj sshrand.obj
|
OBJS2 = ssh.obj sshcrc.obj sshdes.obj sshmd5.obj sshrsa.obj sshrand.obj
|
||||||
OBJS3 = sshsha.obj sshblowf.obj version.obj sizetip.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
|
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
|
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 /debug -out:puttyd.exe @link.rsp
|
||||||
|
|
||||||
link.rsp: makefile
|
link.rsp: makefile
|
||||||
echo /nologo /subsystem:windows > link.rsp
|
echo /nologo /subsystem:windows > link.rsp
|
||||||
echo $(PUTTYOBJS) >> link.rsp
|
echo $(POBJS1) >> link.rsp
|
||||||
|
echo $(POBJS2) >> link.rsp
|
||||||
echo $(OBJS1) >> link.rsp
|
echo $(OBJS1) >> link.rsp
|
||||||
echo $(OBJS2) >> link.rsp
|
echo $(OBJS2) >> link.rsp
|
||||||
echo $(OBJS3) >> link.rsp
|
echo $(OBJS3) >> link.rsp
|
||||||
@ -49,6 +51,7 @@ sizetip.obj: sizetip.c putty.h
|
|||||||
telnet.obj: telnet.c putty.h
|
telnet.obj: telnet.c putty.h
|
||||||
raw.obj: raw.c putty.h
|
raw.obj: raw.c putty.h
|
||||||
xlat.obj: xlat.c putty.h
|
xlat.obj: xlat.c putty.h
|
||||||
|
ldisc.obj: ldisc.c putty.h
|
||||||
misc.obj: misc.c putty.h
|
misc.obj: misc.c putty.h
|
||||||
noise.obj: noise.c putty.h ssh.h
|
noise.obj: noise.c putty.h ssh.h
|
||||||
ssh.obj: ssh.c ssh.h putty.h
|
ssh.obj: ssh.c ssh.h putty.h
|
||||||
|
137
ldisc.c
Normal file
137
ldisc.c
Normal 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
13
putty.h
@ -91,6 +91,12 @@ typedef struct {
|
|||||||
|
|
||||||
GLOBAL Backend *back;
|
GLOBAL Backend *back;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void (*send) (char *buf, int len);
|
||||||
|
} Ldisc;
|
||||||
|
|
||||||
|
GLOBAL Ldisc *ldisc;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Basic options */
|
/* Basic options */
|
||||||
char host[512];
|
char host[512];
|
||||||
@ -117,6 +123,7 @@ typedef struct {
|
|||||||
int nethack_keypad;
|
int nethack_keypad;
|
||||||
int alt_f4; /* is it special? */
|
int alt_f4; /* is it special? */
|
||||||
int alt_space; /* is it special? */
|
int alt_space; /* is it special? */
|
||||||
|
int ldisc_term;
|
||||||
/* Terminal options */
|
/* Terminal options */
|
||||||
int savelines;
|
int savelines;
|
||||||
int dec_om;
|
int dec_om;
|
||||||
@ -232,6 +239,12 @@ extern Backend telnet_backend;
|
|||||||
|
|
||||||
extern Backend ssh_backend;
|
extern Backend ssh_backend;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exports from ldisc.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern Ldisc ldisc_term, ldisc_simple;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exports from sshrand.c.
|
* Exports from sshrand.c.
|
||||||
*/
|
*/
|
||||||
|
14
terminal.c
14
terminal.c
@ -577,7 +577,7 @@ void term_out(void) {
|
|||||||
do_toplevel:
|
do_toplevel:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\005': /* terminal type query */
|
case '\005': /* terminal type query */
|
||||||
back->send ("\033[?1;2c", 7);
|
ldisc->send ("\033[?1;2c", 7);
|
||||||
break;
|
break;
|
||||||
case '\007':
|
case '\007':
|
||||||
beep();
|
beep();
|
||||||
@ -766,7 +766,7 @@ void term_out(void) {
|
|||||||
must_update = TRUE;
|
must_update = TRUE;
|
||||||
break;
|
break;
|
||||||
case 'Z': /* terminal type query */
|
case 'Z': /* terminal type query */
|
||||||
back->send ("\033[?6c", 5);
|
ldisc->send ("\033[?6c", 5);
|
||||||
break;
|
break;
|
||||||
case 'c': /* restore power-on settings */
|
case 'c': /* restore power-on settings */
|
||||||
power_on();
|
power_on();
|
||||||
@ -902,13 +902,13 @@ void term_out(void) {
|
|||||||
must_update = TRUE;
|
must_update = TRUE;
|
||||||
break;
|
break;
|
||||||
case 'c': /* terminal type query */
|
case 'c': /* terminal type query */
|
||||||
back->send ("\033[?6c", 5);
|
ldisc->send ("\033[?6c", 5);
|
||||||
break;
|
break;
|
||||||
case 'n': /* cursor position query */
|
case 'n': /* cursor position query */
|
||||||
if (esc_args[0] == 6) {
|
if (esc_args[0] == 6) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
sprintf (buf, "\033[%d;%dR", curs_y + 1, curs_x + 1);
|
sprintf (buf, "\033[%d;%dR", curs_y + 1, curs_x + 1);
|
||||||
back->send (buf, strlen(buf));
|
ldisc->send (buf, strlen(buf));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'h': /* toggle a mode to high */
|
case 'h': /* toggle a mode to high */
|
||||||
@ -1031,7 +1031,7 @@ void term_out(void) {
|
|||||||
if (i == 0 || i == 1) {
|
if (i == 0 || i == 1) {
|
||||||
strcpy (buf, "\033[2;1;1;112;112;1;0x");
|
strcpy (buf, "\033[2;1;1;112;112;1;0x");
|
||||||
buf[2] += i;
|
buf[2] += i;
|
||||||
back->send (buf, 20);
|
ldisc->send (buf, 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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++)
|
for(i=0;i<p-q;i++)
|
||||||
{
|
{
|
||||||
c=xlat_kbd2tty(q[i]);
|
c=xlat_kbd2tty(q[i]);
|
||||||
back->send(&c,1);
|
ldisc->send(&c,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p <= data+len-sizeof(sel_nl) &&
|
if (p <= data+len-sizeof(sel_nl) &&
|
||||||
!memcmp(p, sel_nl, sizeof(sel_nl))) {
|
!memcmp(p, sel_nl, sizeof(sel_nl))) {
|
||||||
back->send ("\r", 1);
|
ldisc->send ("\r", 1);
|
||||||
p += sizeof(sel_nl);
|
p += sizeof(sel_nl);
|
||||||
}
|
}
|
||||||
q = p;
|
q = p;
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
#define IDC1_CURAPPLIC 1016
|
#define IDC1_CURAPPLIC 1016
|
||||||
#define IDC1_ALTF4 1017
|
#define IDC1_ALTF4 1017
|
||||||
#define IDC1_ALTSPACE 1018
|
#define IDC1_ALTSPACE 1018
|
||||||
|
#define IDC1_LDISCTERM 1019
|
||||||
|
|
||||||
#define IDC2_WRAPMODE 1001
|
#define IDC2_WRAPMODE 1001
|
||||||
#define IDC2_DECOM 1002
|
#define IDC2_DECOM 1002
|
||||||
|
@ -105,6 +105,8 @@ BEGIN
|
|||||||
IDC1_ALTF4, 3, 113, 162, 10
|
IDC1_ALTF4, 3, 113, 162, 10
|
||||||
AUTOCHECKBOX "ALT-Space is special (S&ystem menu)",
|
AUTOCHECKBOX "ALT-Space is special (S&ystem menu)",
|
||||||
IDC1_ALTSPACE, 3, 123, 162, 10
|
IDC1_ALTSPACE, 3, 123, 162, 10
|
||||||
|
AUTOCHECKBOX "&Use local terminal line discipline",
|
||||||
|
IDC1_LDISCTERM, 3, 133, 162, 10
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
|
IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
|
||||||
|
8
windlg.c
8
windlg.c
@ -157,6 +157,7 @@ static void save_settings (char *section, int do_host) {
|
|||||||
wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
|
wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
|
||||||
wppi (sesskey, "AltF4", cfg.alt_f4);
|
wppi (sesskey, "AltF4", cfg.alt_f4);
|
||||||
wppi (sesskey, "AltSpace", cfg.alt_space);
|
wppi (sesskey, "AltSpace", cfg.alt_space);
|
||||||
|
wppi (sesskey, "LdiscTerm", cfg.ldisc_term);
|
||||||
wppi (sesskey, "ScrollbackLines", cfg.savelines);
|
wppi (sesskey, "ScrollbackLines", cfg.savelines);
|
||||||
wppi (sesskey, "DECOriginMode", cfg.dec_om);
|
wppi (sesskey, "DECOriginMode", cfg.dec_om);
|
||||||
wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
|
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, "NetHackKeypad", 0, &cfg.nethack_keypad);
|
||||||
gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
|
gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
|
||||||
gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
|
gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
|
||||||
|
gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
|
||||||
gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
|
gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
|
||||||
gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
|
gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
|
||||||
gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
|
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);
|
cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
|
||||||
CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
|
CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
|
||||||
CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
|
CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
|
||||||
|
CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
|
||||||
break;
|
break;
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
if (HIWORD(wParam) == BN_CLICKED ||
|
if (HIWORD(wParam) == BN_CLICKED ||
|
||||||
@ -676,6 +679,11 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
|
|||||||
HIWORD(wParam) == BN_DOUBLECLICKED)
|
HIWORD(wParam) == BN_DOUBLECLICKED)
|
||||||
cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
|
cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
|
||||||
break;
|
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);
|
return GeneralPanelProc (hwnd, msg, wParam, lParam);
|
||||||
|
9
window.c
9
window.c
@ -181,7 +181,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
back = (cfg.protocol == PROT_SSH ? &ssh_backend :
|
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) {
|
if (!prev) {
|
||||||
wndclass.style = 0;
|
wndclass.style = 0;
|
||||||
@ -1016,7 +1019,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
|
|||||||
len = TranslateKey (wParam, lParam, buf);
|
len = TranslateKey (wParam, lParam, buf);
|
||||||
if (len == -1)
|
if (len == -1)
|
||||||
return DefWindowProc (hwnd, message, wParam, lParam);
|
return DefWindowProc (hwnd, message, wParam, lParam);
|
||||||
back->send (buf, len);
|
ldisc->send (buf, len);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
@ -1056,7 +1059,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char c = xlat_kbd2tty((unsigned char)wParam);
|
char c = xlat_kbd2tty((unsigned char)wParam);
|
||||||
back->send (&c, 1);
|
ldisc->send (&c, 1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user