Changes from executor:
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 9 Nov 1999 11:10:04 +0000 (11:10 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 9 Nov 1999 11:10:04 +0000 (11:10 +0000)
 - 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

git-svn-id: svn://svn.tartarus.org/sgt/putty@284 cda61777-01e9-0310-a592-d414129be87e

putty.h
ssh.c
ssh.h
sshblowf.c
sshdes.c
telnet.c
win_res.h
win_res.rc
windlg.c
window.c

diff --git a/putty.h b/putty.h
index 1360915..e5744ea 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -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);
diff --git a/ssh.c b/ssh.c
index e61654a..93a1280 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -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) {
diff --git a/ssh.h b/ssh.h
index 2aac856..68e5a12 100644 (file)
--- a/ssh.h
+++ b/ssh.h
@@ -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 *);
index 1bf64ad..5451c2d 100644 (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)
index aa6b94f..83d4d26 100644 (file)
--- a/sshdes.c
+++ b/sshdes.c
@@ -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) {
index 20341cd..33b921b 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -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);
 }
 
 /*
index 3e8cb30..aec42f6 100644 (file)
--- a/win_res.h
+++ b/win_res.h
 #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
index d71f0e3..37b5eca 100644 (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
index 1d0604e..69f91fb 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -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);
index 2581623..6afd10e 100644 (file)
--- a/window.c
+++ b/window.c
@@ -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