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

Changes from executor:

- NetHack keypad mode (Shift only works with NumLock off)
 - Alt-Space handling (best I could manage; not too bad considering)
 - Event Log rather than Telnet Negotiation Log

[originally from svn r284]
This commit is contained in:
Simon Tatham 1999-11-09 11:10:04 +00:00
parent 59e798fc6d
commit f6c63320ea
10 changed files with 189 additions and 65 deletions

View File

@ -114,6 +114,9 @@ typedef struct {
int linux_funkeys;
int app_cursor;
int app_keypad;
int nethack_keypad;
int alt_f4; /* is it special? */
int alt_space; /* is it special? */
/* Terminal options */
int savelines;
int dec_om;
@ -186,8 +189,8 @@ void random_save_seed(void);
int do_config (void);
int do_reconfig (HWND);
void do_defaults (char *);
void lognegot (char *);
void shownegot (HWND);
void logevent (char *);
void showeventlog (HWND);
void showabout (HWND);
void verify_ssh_host_key(char *host, struct RSAKey *key);
void get_sesslist(int allocate);

67
ssh.c
View File

@ -251,9 +251,10 @@ static int ssh_versioncmp(char *a, char *b) {
}
static int do_ssh_init(void) {
char c;
char c, *vsp;
char version[10];
char vstring[40];
char vstring[80];
char vlog[sizeof(vstring)+20];
int i;
#ifdef FWHACK
@ -269,11 +270,15 @@ static int do_ssh_init(void) {
if (s_read(&c,1) != 1 || c != 'S') return 0;
if (s_read(&c,1) != 1 || c != 'H') return 0;
#endif
strcpy(vstring, "SSH-");
vsp = vstring+4;
if (s_read(&c,1) != 1 || c != '-') return 0;
i = 0;
while (1) {
if (s_read(&c,1) != 1)
return 0;
if (vsp < vstring+sizeof(vstring)-1)
*vsp++ = c;
if (i >= 0) {
if (c == '-') {
version[i] = '\0';
@ -285,8 +290,16 @@ static int do_ssh_init(void) {
break;
}
*vsp = 0;
sprintf(vlog, "Server version: %s", vstring);
vlog[strcspn(vlog, "\r\n")] = '\0';
logevent(vlog);
sprintf(vstring, "SSH-%s-PuTTY\n",
(ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5"));
sprintf(vlog, "We claim version: %s", vstring);
vlog[strcspn(vlog, "\r\n")] = '\0';
logevent(vlog);
s_write(vstring, strlen(vstring));
return 1;
}
@ -315,14 +328,33 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
if (pktin.type != SSH_SMSG_PUBLIC_KEY)
fatalbox("Public key packet not received");
memcpy(cookie, pktin.body, 8);
logevent("Received public keys");
MD5Init(&md5c);
memcpy(cookie, pktin.body, 8);
i = makekey(pktin.body+8, &servkey, &keystr1);
j = makekey(pktin.body+8+i, &hostkey, &keystr2);
/*
* Hash the host key and print the hash in the log box. Just as
* a last resort in case the registry's host key checking is
* compromised, we'll allow the user some ability to verify
* host keys by eye.
*/
MD5Init(&md5c);
MD5Update(&md5c, keystr2, hostkey.bytes);
MD5Final(session_id, &md5c);
{
char logmsg[80];
int i;
logevent("Host key MD5 is:");
strcpy(logmsg, " ");
for (i = 0; i < 16; i++)
sprintf(logmsg+strlen(logmsg), "%02x", session_id[i]);
logevent(logmsg);
}
supported_ciphers_mask = ((pktin.body[12+i+j] << 24) |
(pktin.body[13+i+j] << 16) |
(pktin.body[14+i+j] << 8) |
@ -333,6 +365,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
(pktin.body[18+i+j] << 8) |
(pktin.body[19+i+j]));
MD5Init(&md5c);
MD5Update(&md5c, keystr2, hostkey.bytes);
MD5Update(&md5c, keystr1, servkey.bytes);
MD5Update(&md5c, pktin.body, 8);
@ -364,6 +398,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
rsaencrypt(rsabuf, hostkey.bytes, &servkey);
}
logevent("Encrypted session key");
cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH :
cfg.cipher == CIPHER_DES ? SSH_CIPHER_DES :
SSH_CIPHER_3DES;
@ -371,6 +407,11 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
c_write("Selected cipher not supported, falling back to 3DES\r\n", 53);
cipher_type = SSH_CIPHER_3DES;
}
switch (cipher_type) {
case SSH_CIPHER_3DES: logevent("Using 3DES encryption"); break;
case SSH_CIPHER_DES: logevent("Using single-DES encryption"); break;
case SSH_CIPHER_BLOWFISH: logevent("Using Blowfish encryption"); break;
}
s_wrpkt_start(SSH_CMSG_SESSION_KEY, len+15);
pktout.body[0] = cipher_type;
@ -381,6 +422,7 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
pktout.body[len+11] = pktout.body[len+12] = 0; /* protocol flags */
pktout.body[len+13] = pktout.body[len+14] = 0;
s_wrpkt();
logevent("Trying to enable encryption...");
free(rsabuf);
@ -394,6 +436,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
if (pktin.type != SSH_SMSG_SUCCESS)
fatalbox("Encryption not successfully enabled");
logevent("Successfully started encryption");
fflush(stdout);
{
static char username[100];
@ -442,6 +486,11 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
c_write(stuff, strlen(stuff));
}
s_wrpkt_start(SSH_CMSG_USER, 4+strlen(username));
{
char userlog[20+sizeof(username)];
sprintf(userlog, "Sent username \"%s\"", username);
logevent(userlog);
}
pktout.body[0] = pktout.body[1] = pktout.body[2] = 0;
pktout.body[3] = strlen(username);
memcpy(pktout.body+4, username, strlen(username));
@ -465,16 +514,19 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
cfg.try_tis_auth &&
(supported_auths_mask & (1<<SSH_AUTH_TIS))) {
pwpkt_type = SSH_CMSG_AUTH_TIS_RESPONSE;
logevent("Requested TIS authentication");
s_wrpkt_start(SSH_CMSG_AUTH_TIS, 0);
s_wrpkt();
do { crReturnV; } while (!ispkt);
if (pktin.type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
logevent("TIS authentication declined");
c_write("TIS authentication refused.\r\n", 29);
} else {
int challengelen = ((pktin.body[0] << 24) |
(pktin.body[1] << 16) |
(pktin.body[2] << 8) |
(pktin.body[3]));
logevent("Received TIS challenge");
c_write(pktin.body+4, challengelen);
}
}
@ -512,15 +564,19 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
pktout.body[3] = strlen(password);
memcpy(pktout.body+4, password, strlen(password));
s_wrpkt();
logevent("Sent password");
memset(password, 0, strlen(password));
do { crReturnV; } while (!ispkt);
if (pktin.type == 15) {
c_write("Access denied\r\n", 15);
logevent("Authentication refused");
} else if (pktin.type != 14) {
fatalbox("Strange packet received, type %d", pktin.type);
}
}
logevent("Authentication successful");
if (!cfg.nopty) {
i = strlen(cfg.termtype);
s_wrpkt_start(SSH_CMSG_REQUEST_PTY, i+5*4+1);
@ -547,10 +603,12 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
} else if (pktin.type == SSH_SMSG_FAILURE) {
c_write("Server refused to allocate pty\r\n", 32);
}
logevent("Allocated pty");
}
s_wrpkt_start(SSH_CMSG_EXEC_SHELL, 0);
s_wrpkt();
logevent("Started session");
ssh_state = SSH_STATE_SESSION;
if (size_needed)
@ -567,6 +625,7 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
c_write(pktin.body+4, len);
} else if (pktin.type == SSH_MSG_DISCONNECT) {
ssh_state = SSH_STATE_CLOSED;
logevent("Received disconnect request");
} else if (pktin.type == SSH_SMSG_SUCCESS) {
/* may be from EXEC_SHELL on some servers */
} else if (pktin.type == SSH_SMSG_FAILURE) {

2
ssh.h
View File

@ -44,3 +44,5 @@ void SHATransform(word32 *digest, word32 *data);
int random_byte(void);
void random_add_noise(void *noise, int length);
void logevent (char *);

View File

@ -396,6 +396,7 @@ static void blowfish_sesskey(unsigned char *key)
ectx.iv0 = 0;
ectx.iv1 = 0;
dctx = ectx;
logevent("Initialised Blowfish encryption");
}
static void blowfish_encrypt_blk(unsigned char *blk, int len)

View File

@ -657,6 +657,7 @@ static void des3_sesskey(unsigned char *key) {
memset(div1, 0, sizeof(div1));
memset(div2, 0, sizeof(div2));
memset(div3, 0, sizeof(div3));
logevent("Initialised triple-DES encryption");
}
static void des3_encrypt_blk(unsigned char *blk, int len) {
@ -678,6 +679,7 @@ static void des_sesskey(unsigned char *key) {
memset(eiv1, 0, sizeof(eiv1));
des_set_key(key, &dkey1);
memset(div1, 0, sizeof(div1));
logevent("Initialised single-DES encryption");
}
static void des_encrypt_blk(unsigned char *blk, int len) {

View File

@ -184,7 +184,7 @@ static void log_option (char *sender, int cmd, int option) {
(cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
telopt(option));
lognegot(buf);
logevent(buf);
}
static void send_opt (int cmd, int option) {
@ -285,11 +285,11 @@ static void process_subneg (void) {
n = 4 + strlen(cfg.termspeed);
b[n] = IAC; b[n+1] = SE;
s_write (b, n+2);
lognegot("server:\tSB TSPEED SEND");
logevent("server:\tSB TSPEED SEND");
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
lognegot (logbuf);
logevent (logbuf);
} else
lognegot ("server:\tSB TSPEED <something weird>");
logevent ("server:\tSB TSPEED <something weird>");
break;
case TELOPT_TTYPE:
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
@ -302,11 +302,11 @@ static void process_subneg (void) {
b[n+4] = IAC; b[n+5] = SE;
s_write (b, n+6);
b[n+4] = 0;
lognegot("server:\tSB TTYPE SEND");
logevent("server:\tSB TTYPE SEND");
sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4);
lognegot(logbuf);
logevent(logbuf);
} else
lognegot("server:\tSB TTYPE <something weird>\r\n");
logevent("server:\tSB TTYPE <something weird>\r\n");
break;
case TELOPT_OLD_ENVIRON:
case TELOPT_NEW_ENVIRON:
@ -316,7 +316,7 @@ static void process_subneg (void) {
char logbuf[50];
p++;
sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt));
lognegot (logbuf);
logevent (logbuf);
if (sb_opt == TELOPT_OLD_ENVIRON) {
if (cfg.rfc_environ) {
value = RFC_VALUE;
@ -368,7 +368,7 @@ static void process_subneg (void) {
s_write (b, n);
sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
n==6 ? "<nothing>" : "<stuff>");
lognegot (logbuf);
logevent (logbuf);
}
break;
}
@ -681,7 +681,7 @@ static void telnet_size(void) {
sprintf(logbuf, "client:\tSB NAWS %d,%d",
((unsigned char)b[3] << 8) + (unsigned char)b[4],
((unsigned char)b[5] << 8) + (unsigned char)b[6]);
lognegot (logbuf);
logevent (logbuf);
}
/*

View File

@ -57,9 +57,12 @@
#define IDC1_KPSTATIC 1010
#define IDC1_KPNORMAL 1011
#define IDC1_KPAPPLIC 1012
#define IDC1_CURSTATIC 1013
#define IDC1_CURNORMAL 1014
#define IDC1_CURAPPLIC 1015
#define IDC1_KPNH 1013
#define IDC1_CURSTATIC 1014
#define IDC1_CURNORMAL 1015
#define IDC1_CURAPPLIC 1016
#define IDC1_ALTF4 1017
#define IDC1_ALTSPACE 1018
#define IDC2_WRAPMODE 1001
#define IDC2_DECOM 1002

View File

@ -77,28 +77,34 @@ STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Action of Backspace:", IDC1_DELSTATIC, 3, 3, 162, 8
AUTORADIOBUTTON "Control-&H (ASCII 8)", IDC1_DEL008, 3, 12, 162, 10, WS_GROUP
AUTORADIOBUTTON "Control-&? (ASCII 127)", IDC1_DEL127, 3, 22, 162, 10
LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 35, 162, 8
AUTORADIOBUTTON "&Standard (ESC [ 1 ~ and ESC [ 4 ~)",
IDC1_HOMETILDE, 3, 44, 162, 10, WS_GROUP
AUTORADIOBUTTON "&rxvt (ESC [ H and ESC O w)",
IDC1_HOMERXVT, 3, 54, 162, 10
LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 67, 162, 8
AUTORADIOBUTTON "S&tandard (ESC [ 11 ~ through ESC [ 15 ~)",
IDC1_FUNCTILDE, 3, 76, 162, 10, WS_GROUP
AUTORADIOBUTTON "&Linux (ESC [ [ A through ESC [ [ E)",
IDC1_FUNCLINUX, 3, 86, 162, 10
LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 99, 162, 8
AUTORADIOBUTTON "&Normal (depends on NumLock)",
IDC1_KPNORMAL, 3, 108, 162, 10, WS_GROUP
AUTORADIOBUTTON "A&pplication (ESC O P etc)",
IDC1_KPAPPLIC, 3, 118, 162, 10
LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 131, 162, 8
AUTORADIOBUTTON "Nor&mal (ESC [ A through ESC [ D)",
IDC1_CURNORMAL, 3, 140, 162, 10, WS_GROUP
AUTORADIOBUTTON "Appl&ication (ESC O A through ESC O D)",
IDC1_CURAPPLIC, 3, 150, 162, 10
AUTORADIOBUTTON "Control-&H", IDC1_DEL008, 3, 12, 50, 10, WS_GROUP
AUTORADIOBUTTON "Control-&? (127)", IDC1_DEL127, 62, 12, 100, 10
LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 25, 162, 8
AUTORADIOBUTTON "&Standard",
IDC1_HOMETILDE, 3, 34, 50, 10, WS_GROUP
AUTORADIOBUTTON "&rxvt",
IDC1_HOMERXVT, 62, 34, 50, 10
LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 47, 162, 8
AUTORADIOBUTTON "S&tandard",
IDC1_FUNCTILDE, 3, 56, 50, 10, WS_GROUP
AUTORADIOBUTTON "&Linux console",
IDC1_FUNCLINUX, 62, 56, 100, 10
LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 69, 162, 8
AUTORADIOBUTTON "&Normal",
IDC1_CURNORMAL, 3, 78, 50, 10, WS_GROUP
AUTORADIOBUTTON "A&pplication",
IDC1_CURAPPLIC, 62, 78, 50, 10
LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 91, 162, 8
AUTORADIOBUTTON "Nor&mal",
IDC1_KPNORMAL, 3, 100, 50, 10, WS_GROUP
AUTORADIOBUTTON "Appl&ication",
IDC1_KPAPPLIC, 62, 100, 50, 10
AUTORADIOBUTTON "N&etHack",
IDC1_KPNH, 121, 100, 50, 10
AUTOCHECKBOX "ALT-F&4 is special (closes window)",
IDC1_ALTF4, 3, 113, 162, 10
AUTOCHECKBOX "ALT-Space is special (S&ystem menu)",
IDC1_ALTSPACE, 3, 123, 162, 10
END
IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
@ -217,7 +223,7 @@ END
IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 160, 119
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Negotiation Log"
CAPTION "PuTTY Event Log"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&Close", IDOK, 58, 102, 44, 14

View File

@ -15,8 +15,9 @@
static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
static char **negots = NULL;
static int nnegots = 0, negsize = 0;
static char **events = NULL;
static int nevents = 0, negsize = 0;
static HWND logbox = NULL, abtbox = NULL;
static char hex[16] = "0123456789ABCDEF";
@ -153,6 +154,9 @@ static void save_settings (char *section, int do_host) {
wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
wppi (sesskey, "AltF4", cfg.alt_f4);
wppi (sesskey, "AltSpace", cfg.alt_space);
wppi (sesskey, "ScrollbackLines", cfg.savelines);
wppi (sesskey, "DECOriginMode", cfg.dec_om);
wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
@ -283,6 +287,9 @@ static void load_settings (char *section, int do_host) {
gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
@ -355,9 +362,9 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg,
switch (msg) {
case WM_INITDIALOG:
for (i=0; i<nnegots; i++)
for (i=0; i<nevents; i++)
SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
0, (LPARAM)negots[i]);
0, (LPARAM)events[i]);
return 1;
/* case WM_CTLCOLORDLG: */
/* return (int) GetStockObject (LTGRAY_BRUSH); */
@ -624,8 +631,11 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPAPPLIC,
CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
cfg.nethack_keypad ? IDC1_KPNH :
cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED ||
@ -646,11 +656,26 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
case IDC1_KPNORMAL:
case IDC1_KPAPPLIC:
cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
cfg.nethack_keypad = FALSE;
break;
case IDC1_KPNH:
cfg.app_keypad = FALSE;
cfg.nethack_keypad = TRUE;
break;
case IDC1_CURNORMAL:
case IDC1_CURAPPLIC:
cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
break;
case IDC1_ALTF4:
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED)
cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
break;
case IDC1_ALTSPACE:
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED)
cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
break;
}
}
return GeneralPanelProc (hwnd, msg, wParam, lParam);
@ -1361,20 +1386,20 @@ void do_defaults (char *session) {
load_settings ("Default Settings", FALSE);
}
void lognegot (char *string) {
if (nnegots >= negsize) {
void logevent (char *string) {
if (nevents >= negsize) {
negsize += 64;
negots = srealloc (negots, negsize * sizeof(*negots));
events = srealloc (events, negsize * sizeof(*events));
}
negots[nnegots] = smalloc(1+strlen(string));
strcpy (negots[nnegots], string);
nnegots++;
events[nevents] = smalloc(1+strlen(string));
strcpy (events[nevents], string);
nevents++;
if (logbox)
SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
0, (LPARAM)string);
}
void shownegot (HWND hwnd) {
void showeventlog (HWND hwnd) {
if (!logbox) {
logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
hwnd, LogProc);

View File

@ -341,9 +341,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
AppendMenu (p, MF_ENABLED, IDM_TEL_EOR, "End Of Record");
AppendMenu (p, MF_ENABLED, IDM_TEL_EOF, "End Of File");
AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) p, "Telnet Command");
AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "Show Negotiation");
AppendMenu (m, MF_SEPARATOR, 0, 0);
}
AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "Event Log");
AppendMenu (m, MF_SEPARATOR, 0, 0);
AppendMenu (m, MF_ENABLED, IDM_NEWSESS, "New Session");
AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "Duplicate Session");
s = CreateMenu();
@ -628,7 +629,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
case WM_SYSCOMMAND:
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
case IDM_SHOWLOG:
shownegot(hwnd);
showeventlog(hwnd);
break;
case IDM_NEWSESS:
case IDM_DUPSESS:
@ -1013,6 +1014,8 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
int len;
len = TranslateKey (wParam, lParam, buf);
if (len == -1)
return DefWindowProc (hwnd, message, wParam, lParam);
back->send (buf, len);
}
return 0;
@ -1253,9 +1256,12 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
return 0;
}
if ((lParam & 0x20000000) && wParam == VK_F4) {
SendMessage (hwnd, WM_CLOSE, 0, 0);
return 0;
if ((lParam & 0x20000000) && wParam == VK_F4 && cfg.alt_f4) {
return -1;
}
if ((lParam & 0x20000000) && wParam == VK_SPACE && cfg.alt_space) {
SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
return -1;
}
/*
@ -1281,12 +1287,29 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
return p - output;
}
/*
* If we're in applications keypad mode, we have to process it
* before char-map translation, because it will pre-empt lots
* of stuff, even if NumLock is off.
*/
if (app_keypad_keys) {
if (cfg.nethack_keypad) {
int shift = keystate[VK_SHIFT] & 0x80;
/*
* NB the shifted versions only work with numlock off.
*/
switch ( (lParam >> 16) & 0x1FF ) {
case 0x047: *p++ = shift ? 'Y' : 'y'; return p - output;
case 0x048: *p++ = shift ? 'K' : 'k'; return p - output;
case 0x049: *p++ = shift ? 'U' : 'u'; return p - output;
case 0x04B: *p++ = shift ? 'H' : 'h'; return p - output;
case 0x04C: *p++ = '.'; return p - output;
case 0x04D: *p++ = shift ? 'L' : 'l'; return p - output;
case 0x04F: *p++ = shift ? 'B' : 'b'; return p - output;
case 0x050: *p++ = shift ? 'J' : 'j'; return p - output;
case 0x051: *p++ = shift ? 'N' : 'n'; return p - output;
case 0x053: *p++ = '.'; return p - output;
}
} else if (app_keypad_keys) {
/*
* If we're in applications keypad mode, we have to process it
* before char-map translation, because it will pre-empt lots
* of stuff, even if NumLock is off.
*/
if (ret) {
/*
* Hack to ensure NumLock doesn't interfere with