Ensure our network layer is properly cleaned up before PuTTY exits.
[u/mdw/putty] / windlg.c
index cb7500c..20d7fc2 100644 (file)
--- a/windlg.c
+++ b/windlg.c
 #include "win_res.h"
 #include "storage.h"
 
+#ifdef MSVC4
+#define TVINSERTSTRUCT  TV_INSERTSTRUCT
+#define TVITEM          TV_ITEM
+#define ICON_BIG        1
+#endif
+
 static char **events = NULL;
 static int nevents = 0, negsize = 0;
 
 static int readytogo;
 static int sesslist_has_focus;
+static int requested_help;
 
 static struct prefslist cipherlist;
 
@@ -256,6 +263,7 @@ enum { IDCX_ABOUT =
     IDC_LSTATOFF,
     IDC_LSTATASCII,
     IDC_LSTATRAW,
+    IDC_LSTATPACKET,
     IDC_LGFSTATIC,
     IDC_LGFEDIT,
     IDC_LGFBUTTON,
@@ -295,7 +303,6 @@ enum { IDCX_ABOUT =
     IDC_CURAPPLIC,
     IDC_COMPOSEKEY,
     IDC_CTRLALTKEYS,
-    IDC_TELNETKEY,
     keyboardpanelend,
 
     terminalpanelstart,
@@ -435,6 +442,8 @@ enum { IDCX_ABOUT =
     IDC_ACTSTATIC,
     IDC_TPASSIVE,
     IDC_TACTIVE,
+    IDC_TELNETKEY,
+    IDC_TELNETRET,
     telnetpanelend,
 
     rloginpanelstart,
@@ -476,6 +485,7 @@ enum { IDCX_ABOUT =
     IDC_PKEDIT,
     IDC_PKBUTTON,
     IDC_AGENTFWD,
+    IDC_CHANGEUSER,
     IDC_AUTHTIS,
     IDC_AUTHKI,
     sshauthpanelend,
@@ -542,6 +552,7 @@ enum { IDCX_ABOUT =
     IDC_X11_DISPSTATIC,
     IDC_X11_DISPLAY,
     IDC_LPORT_ALL,
+    IDC_RPORT_ALL,
     IDC_PFWDSTATIC,
     IDC_PFWDSTATIC2,
     IDC_PFWDREMOVE,
@@ -590,6 +601,332 @@ static void fmtfont(char *buf)
                (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight));
 }
 
+char *help_context_cmd(int id)
+{
+    switch (id) {
+      case IDC_HOSTSTATIC:
+      case IDC_HOST:
+      case IDC_PORTSTATIC:
+      case IDC_PORT:
+      case IDC_PROTSTATIC:
+      case IDC_PROTRAW:
+      case IDC_PROTTELNET:
+      case IDC_PROTRLOGIN:
+      case IDC_PROTSSH:
+        return "JI(`',`session.hostname')";
+      case IDC_SESSSTATIC:
+      case IDC_SESSEDIT:
+      case IDC_SESSLIST:
+      case IDC_SESSLOAD:
+      case IDC_SESSSAVE:
+      case IDC_SESSDEL:
+        return "JI(`',`session.saved')";
+      case IDC_CLOSEEXIT:
+      case IDC_COEALWAYS:
+      case IDC_COENEVER:
+      case IDC_COENORMAL:
+        return "JI(`',`session.coe')";
+      case IDC_LSTATSTATIC:
+      case IDC_LSTATOFF:
+      case IDC_LSTATASCII:
+      case IDC_LSTATRAW:
+      case IDC_LSTATPACKET:
+        return "JI(`',`logging.main')";
+      case IDC_LGFSTATIC:
+      case IDC_LGFEDIT:
+      case IDC_LGFBUTTON:
+      case IDC_LGFEXPLAIN:
+        return "JI(`',`logging.filename')";
+      case IDC_LSTATXIST:
+      case IDC_LSTATXOVR:
+      case IDC_LSTATXAPN:
+      case IDC_LSTATXASK:
+        return "JI(`',`logging.exists')";
+
+      case IDC_DELSTATIC:
+      case IDC_DEL008:
+      case IDC_DEL127:
+        return "JI(`',`keyboard.backspace')";
+      case IDC_HOMESTATIC:
+      case IDC_HOMETILDE:
+      case IDC_HOMERXVT:
+        return "JI(`',`keyboard.homeend')";
+      case IDC_FUNCSTATIC:
+      case IDC_FUNCTILDE:
+      case IDC_FUNCLINUX:
+      case IDC_FUNCXTERM:
+      case IDC_FUNCVT400:
+      case IDC_FUNCVT100P:
+      case IDC_FUNCSCO:
+        return "JI(`',`keyboard.funkeys')";
+      case IDC_KPSTATIC:
+      case IDC_KPNORMAL:
+      case IDC_KPAPPLIC:
+      case IDC_NOAPPLICK:
+        return "JI(`',`keyboard.appkeypad')";
+      case IDC_NOAPPLICC:
+      case IDC_CURSTATIC:
+      case IDC_CURNORMAL:
+      case IDC_CURAPPLIC:
+        return "JI(`',`keyboard.appcursor')";
+      case IDC_KPNH:
+        return "JI(`',`keyboard.nethack')";
+      case IDC_COMPOSEKEY:
+        return "JI(`',`keyboard.compose')";
+      case IDC_CTRLALTKEYS:
+        return "JI(`',`keyboard.ctrlalt')";
+
+      case IDC_WRAPMODE:
+        return "JI(`',`terminal.autowrap')";
+      case IDC_DECOM:
+        return "JI(`',`terminal.decom')";
+      case IDC_LFHASCR:
+        return "JI(`',`terminal.lfhascr')";
+      case IDC_BCE:
+        return "JI(`',`terminal.bce')";
+      case IDC_BLINKTEXT:
+        return "JI(`',`terminal.blink')";
+      case IDC_ANSWERBACK:
+      case IDC_ANSWEREDIT:
+        return "JI(`',`terminal.answerback')";
+      case IDC_ECHOSTATIC:
+      case IDC_ECHOBACKEND:
+      case IDC_ECHOYES:
+      case IDC_ECHONO:
+        return "JI(`',`terminal.localecho')";
+      case IDC_EDITSTATIC:
+      case IDC_EDITBACKEND:
+      case IDC_EDITYES:
+      case IDC_EDITNO:
+        return "JI(`',`terminal.localedit')";
+
+      case IDC_BELLSTATIC:
+      case IDC_BELL_DISABLED:
+      case IDC_BELL_DEFAULT:
+      case IDC_BELL_WAVEFILE:
+      case IDC_BELL_VISUAL:
+      case IDC_BELL_WAVESTATIC:
+      case IDC_BELL_WAVEEDIT:
+      case IDC_BELL_WAVEBROWSE:
+        return "JI(`',`bell.style')";
+      case IDC_B_IND_STATIC:
+      case IDC_B_IND_DISABLED:
+      case IDC_B_IND_FLASH:
+      case IDC_B_IND_STEADY:
+        return "JI(`',`bell.taskbar')";
+      case IDC_BELLOVL:
+      case IDC_BELLOVLNSTATIC:
+      case IDC_BELLOVLN:
+      case IDC_BELLOVLTSTATIC:
+      case IDC_BELLOVLT:
+      case IDC_BELLOVLEXPLAIN:
+      case IDC_BELLOVLSSTATIC:
+      case IDC_BELLOVLS:
+        return "JI(`',`bell.overload')";
+
+      case IDC_ROWSSTATIC:
+      case IDC_ROWSEDIT:
+      case IDC_COLSSTATIC:
+      case IDC_COLSEDIT:
+        return "JI(`',`window.size')";
+      case IDC_RESIZESTATIC:
+      case IDC_RESIZETERM:
+      case IDC_RESIZEFONT:
+      case IDC_RESIZENONE:
+      case IDC_RESIZEEITHER:
+        return "JI(`',`window.resize')";
+      case IDC_SCROLLBAR:
+      case IDC_SCROLLBARFULLSCREEN:
+      case IDC_SAVESTATIC:
+      case IDC_SAVEEDIT:
+      case IDC_SCROLLKEY:
+      case IDC_SCROLLDISP:
+        return "JI(`',`window.scrollback')";
+
+      case IDC_CLOSEWARN:
+        return "JI(`',`behaviour.closewarn')";
+      case IDC_ALTF4:
+        return "JI(`',`behaviour.altf4')";
+      case IDC_ALTSPACE:
+        return "JI(`',`behaviour.altspace')";
+      case IDC_ALTONLY:
+        return "JI(`',`behaviour.altonly')";
+      case IDC_ALWAYSONTOP:
+        return "JI(`',`behaviour.alwaysontop')";
+      case IDC_FULLSCREENONALTENTER:
+        return "JI(`',`behaviour.altenter')";
+
+      case IDC_CURSORSTATIC:
+      case IDC_CURBLOCK:
+      case IDC_CURUNDER:
+      case IDC_CURVERT:
+      case IDC_BLINKCUR:
+        return "JI(`',`appearance.cursor')";
+      case IDC_FONTSTATIC:
+      case IDC_CHOOSEFONT:
+        return "JI(`',`appearance.font')";
+      case IDC_WINTITLE:
+      case IDC_WINEDIT:
+      case IDC_WINNAME:
+        return "JI(`',`appearance.title')";
+      case IDC_HIDEMOUSE:
+        return "JI(`',`appearance.hidemouse')";
+      case IDC_SUNKENEDGE:
+      case IDC_WINBSTATIC:
+      case IDC_WINBEDIT:
+        return "JI(`',`appearance.border')";
+
+      case IDC_TTSTATIC:
+      case IDC_TTEDIT:
+        return "JI(`',`connection.termtype')";
+      case IDC_LOGSTATIC:
+      case IDC_LOGEDIT:
+        return "JI(`',`connection.username')";
+      case IDC_PINGSTATIC:
+      case IDC_PINGEDIT:
+        return "JI(`',`connection.keepalive')";
+      case IDC_NODELAY:
+        return "JI(`',`connection.nodelay')";
+
+      case IDC_TSSTATIC:
+      case IDC_TSEDIT:
+        return "JI(`',`telnet.termspeed')";
+      case IDC_ENVSTATIC:
+      case IDC_VARSTATIC:
+      case IDC_VAREDIT:
+      case IDC_VALSTATIC:
+      case IDC_VALEDIT:
+      case IDC_ENVLIST:
+      case IDC_ENVADD:
+      case IDC_ENVREMOVE:
+        return "JI(`',`telnet.environ')";
+      case IDC_EMSTATIC:
+      case IDC_EMBSD:
+      case IDC_EMRFC:
+        return "JI(`',`telnet.oldenviron')";
+      case IDC_ACTSTATIC:
+      case IDC_TPASSIVE:
+      case IDC_TACTIVE:
+        return "JI(`',`telnet.passive')";
+      case IDC_TELNETKEY:
+        return "JI(`',`telnet.specialkeys')";
+      case IDC_TELNETRET:
+        return "JI(`',`telnet.newline')";
+
+      case IDC_R_TSSTATIC:
+      case IDC_R_TSEDIT:
+        return "JI(`',`rlogin.termspeed')";
+      case IDC_RLLUSERSTATIC:
+      case IDC_RLLUSEREDIT:
+        return "JI(`',`rlogin.localuser')";
+
+      case IDC_NOPTY:
+        return "JI(`',`ssh.nopty')";
+      case IDC_CIPHERSTATIC2:
+      case IDC_CIPHERLIST:
+      case IDC_CIPHERUP:
+      case IDC_CIPHERDN:
+      case IDC_SSH2DES:
+        return "JI(`',`ssh.ciphers')";
+      case IDC_BUGGYMAC:
+        return "JI(`',`ssh.buggymac')";
+      case IDC_SSHPROTSTATIC:
+      case IDC_SSHPROT1:
+      case IDC_SSHPROT2:
+        return "JI(`',`ssh.protocol')";
+      case IDC_CMDSTATIC:
+      case IDC_CMDEDIT:
+        return "JI(`',`ssh.command')";
+      case IDC_COMPRESS:
+        return "JI(`',`ssh.compress')";
+
+      case IDC_PKSTATIC:
+      case IDC_PKEDIT:
+      case IDC_PKBUTTON:
+        return "JI(`',`ssh.auth.privkey')";
+      case IDC_AGENTFWD:
+        return "JI(`',`ssh.auth.agentfwd')";
+      case IDC_CHANGEUSER:
+        return "JI(`',`ssh.auth.changeuser')";
+      case IDC_AUTHTIS:
+        return "JI(`',`ssh.auth.tis')";
+      case IDC_AUTHKI:
+        return "JI(`',`ssh.auth.ki')";
+
+      case IDC_MBSTATIC:
+      case IDC_MBWINDOWS:
+      case IDC_MBXTERM:
+        return "JI(`',`selection.buttons')";
+      case IDC_MOUSEOVERRIDE:
+        return "JI(`',`selection.shiftdrag')";
+      case IDC_SELTYPESTATIC:
+      case IDC_SELTYPELEX:
+      case IDC_SELTYPERECT:
+        return "JI(`',`selection.rect')";
+      case IDC_CCSTATIC:
+      case IDC_CCLIST:
+      case IDC_CCSET:
+      case IDC_CCSTATIC2:
+      case IDC_CCEDIT:
+        return "JI(`',`selection.charclasses')";
+      case IDC_RAWCNP:
+        return "JI(`',`selection.linedraw')";
+      case IDC_RTFPASTE:
+        return "JI(`',`selection.rtf')";
+
+      case IDC_BOLDCOLOUR:
+        return "JI(`',`colours.bold')";
+      case IDC_PALETTE:
+        return "JI(`',`colours.logpal')";
+      case IDC_COLOURSTATIC:
+      case IDC_COLOURLIST:
+      case IDC_RSTATIC:
+      case IDC_GSTATIC:
+      case IDC_BSTATIC:
+      case IDC_RVALUE:
+      case IDC_GVALUE:
+      case IDC_BVALUE:
+      case IDC_CHANGE:
+        return "JI(`',`colours.config')";
+
+      case IDC_CODEPAGESTATIC:
+      case IDC_CODEPAGE:
+        return "JI(`',`translation.codepage')";
+      case IDC_CAPSLOCKCYR:
+        return "JI(`',`translation.cyrillic')";
+      case IDC_VTSTATIC:
+      case IDC_VTXWINDOWS:
+      case IDC_VTOEMANSI:
+      case IDC_VTOEMONLY:
+      case IDC_VTPOORMAN:
+      case IDC_VTUNICODE:
+        return "JI(`',`translation.linedraw')";
+
+      case IDC_X11_FORWARD:
+      case IDC_X11_DISPSTATIC:
+      case IDC_X11_DISPLAY:
+        return "JI(`',`ssh.tunnels.x11')";
+      case IDC_PFWDSTATIC:
+      case IDC_PFWDSTATIC2:
+      case IDC_PFWDREMOVE:
+      case IDC_PFWDLIST:
+      case IDC_PFWDADD:
+      case IDC_SPORTSTATIC:
+      case IDC_SPORTEDIT:
+      case IDC_DPORTSTATIC:
+      case IDC_DPORTEDIT:
+      case IDC_PFWDLOCAL:
+      case IDC_PFWDREMOTE:
+        return "JI(`',`ssh.tunnels.portfwd')";
+      case IDC_LPORT_ALL:
+      case IDC_RPORT_ALL:
+        return "JI(`',`ssh.tunnels.portfwd.localhost')";
+
+      default:
+        return NULL;
+    }
+}
+
 /* 2nd arg: NZ => don't redraw session list (use when loading
  * a new session) */
 static void init_dlg_ctrls(HWND hwnd, int keepsess)
@@ -641,6 +978,7 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     CheckDlgButton(hwnd, IDC_COMPOSEKEY, cfg.compose_key);
     CheckDlgButton(hwnd, IDC_CTRLALTKEYS, cfg.ctrlaltkeys);
     CheckDlgButton(hwnd, IDC_TELNETKEY, cfg.telnet_keyboard);
+    CheckDlgButton(hwnd, IDC_TELNETRET, cfg.telnet_newline);
     CheckRadioButton(hwnd, IDC_ECHOBACKEND, IDC_ECHONO,
                     cfg.localecho == LD_BACKEND ? IDC_ECHOBACKEND :
                     cfg.localecho == LD_YES ? IDC_ECHOYES : IDC_ECHONO);
@@ -709,9 +1047,11 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     SetDlgItemText(hwnd, IDC_RLLUSEREDIT, cfg.localusername);
     SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
     SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
-    CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
-                    cfg.logtype == 0 ? IDC_LSTATOFF :
-                    cfg.logtype == 1 ? IDC_LSTATASCII : IDC_LSTATRAW);
+    CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATPACKET,
+                    cfg.logtype == LGTYP_NONE ? IDC_LSTATOFF :
+                    cfg.logtype == LGTYP_ASCII ? IDC_LSTATASCII :
+                    cfg.logtype == LGTYP_DEBUG ? IDC_LSTATRAW :
+                    IDC_LSTATPACKET);
     CheckRadioButton(hwnd, IDC_LSTATXOVR, IDC_LSTATXASK,
                     cfg.logxfovr == LGXF_OVR ? IDC_LSTATXOVR :
                     cfg.logxfovr == LGXF_ASK ? IDC_LSTATXASK :
@@ -743,6 +1083,7 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     CheckDlgButton(hwnd, IDC_BUGGYMAC, cfg.buggymac);
     CheckDlgButton(hwnd, IDC_SSH2DES, cfg.ssh2_des_cbc);
     CheckDlgButton(hwnd, IDC_AGENTFWD, cfg.agentfwd);
+    CheckDlgButton(hwnd, IDC_CHANGEUSER, cfg.change_username);
     CheckRadioButton(hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
                     cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
     CheckDlgButton(hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
@@ -843,6 +1184,7 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     SetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display);
 
     CheckDlgButton(hwnd, IDC_LPORT_ALL, cfg.lport_acceptall);
+    CheckDlgButton(hwnd, IDC_RPORT_ALL, cfg.rport_acceptall);
     CheckRadioButton(hwnd, IDC_PFWDLOCAL, IDC_PFWDREMOTE, IDC_PFWDLOCAL);
 }
 
@@ -882,7 +1224,7 @@ static HTREEITEM treeview_insert(struct treeview_faff *faff,
 static void create_controls(HWND hwnd, int dlgtype, int panel)
 {
     if (panel == sessionpanelstart) {
-       /* The Session panel. Accelerators used: [acgo] nprtih elsd w */
+       /* The Session panel. Accelerators used: [acgoh] nprtis elvd w */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Basic options for your PuTTY session",
@@ -906,9 +1248,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                          "&Telnet", IDC_PROTTELNET,
                          "Rlog&in", IDC_PROTRLOGIN,
 #ifdef FWHACK
-                         "SS&H/hack",
+                         "&SSH/hack",
 #else
-                         "SS&H",
+                         "&SSH",
 #endif
                          IDC_PROTSSH, NULL);
            }
@@ -918,7 +1260,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            sesssaver(&cp, "Sav&ed Sessions",
                      IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
                      "&Load", IDC_SESSLOAD,
-                     "&Save", IDC_SESSSAVE, "&Delete", IDC_SESSDEL, NULL);
+                     "Sa&ve", IDC_SESSSAVE, "&Delete", IDC_SESSDEL, NULL);
            endbox(&cp);
        }
        beginbox(&cp, NULL, IDC_BOX_SESSION3);
@@ -930,7 +1272,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == loggingpanelstart) {
-       /* The Logging panel. Accelerators used: [acgo] tplfwe */
+       /* The Logging panel. Accelerators used: [acgoh] tplsfwe */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling session logging",
@@ -940,7 +1282,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                 "Session logging:", IDC_LSTATSTATIC,
                 "Logging &turned off completely", IDC_LSTATOFF,
                 "Log &printable output only", IDC_LSTATASCII,
-                "&Log all session output", IDC_LSTATRAW, NULL);
+                "&Log all session output", IDC_LSTATRAW,
+                "Log &SSH packet data", IDC_LSTATPACKET,
+                NULL);
        editbutton(&cp, "Log &file name:",
                   IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
                   IDC_LGFBUTTON);
@@ -955,7 +1299,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == terminalpanelstart) {
-       /* The Terminal panel. Accelerators used: [acgo] wdlen hts */
+       /* The Terminal panel. Accelerators used: [acgoh] wdren lts */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the terminal emulation",
@@ -963,7 +1307,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        beginbox(&cp, "Set various terminal options", IDC_BOX_TERMINAL1);
        checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
        checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
-       checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
+       checkbox(&cp, "Implicit C&R in every LF", IDC_LFHASCR);
        checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
        checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
        multiedit(&cp,
@@ -972,7 +1316,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        endbox(&cp);
 
        beginbox(&cp, "Line discipline options", IDC_BOX_TERMINAL2);
-       radioline(&cp, "Local ec&ho:", IDC_ECHOSTATIC, 3,
+       radioline(&cp, "&Local echo:", IDC_ECHOSTATIC, 3,
                  "Auto", IDC_ECHOBACKEND,
                  "Force on", IDC_ECHOYES, "Force off", IDC_ECHONO, NULL);
        radioline(&cp, "Local line edi&ting:", IDC_EDITSTATIC, 3,
@@ -982,7 +1326,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == bellpanelstart) {
-       /* The Bell panel. Accelerators used: [acgo] bdsm wit */
+       /* The Bell panel. Accelerators used: [acgoh] bdsm wit */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the terminal bell",
@@ -1019,7 +1363,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == keyboardpanelstart) {
-       /* The Keyboard panel. Accelerators used: [acgo] bhf ruyntd */
+       /* The Keyboard panel. Accelerators used: [acgoh] bef ruyntd */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the effects of keys",
@@ -1028,7 +1372,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        radioline(&cp, "The &Backspace key", IDC_DELSTATIC, 2,
                  "Control-H", IDC_DEL008,
                  "Control-? (127)", IDC_DEL127, NULL);
-       radioline(&cp, "The &Home and End keys", IDC_HOMESTATIC, 2,
+       radioline(&cp, "The Home and &End keys", IDC_HOMESTATIC, 2,
                  "Standard", IDC_HOMETILDE, "rxvt", IDC_HOMERXVT, NULL);
        radioline(&cp, "The &Function keys and keypad", IDC_FUNCSTATIC, 3,
                  "ESC[n~", IDC_FUNCTILDE,
@@ -1060,7 +1404,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == windowpanelstart) {
-       /* The Window panel. Accelerators used: [acgo] rmz sdikp */
+       /* The Window panel. Accelerators used: [acgoh] rmz sdikp */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling PuTTY's window",
@@ -1088,7 +1432,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == appearancepanelstart) {
-       /* The Appearance panel. Accelerators used: [acgo] luvb h ti p s */
+       /* The Appearance panel. Accelerators used: [acgoh] luvb n ti p s */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Configure the appearance of PuTTY's window",
@@ -1102,7 +1446,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        endbox(&cp);
        beginbox(&cp, "Set the font used in the terminal window",
                 IDC_BOX_APPEARANCE2);
-       staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
+       staticbtn(&cp, "", IDC_FONTSTATIC, "Cha&nge...", IDC_CHOOSEFONT);
        endbox(&cp);
        beginbox(&cp, "Adjust the use of the window title",
                 IDC_BOX_APPEARANCE3);
@@ -1124,7 +1468,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == behaviourpanelstart) {
-       /* The Behaviour panel. Accelerators used: [acgo] w4yltf */
+       /* The Behaviour panel. Accelerators used: [acgoh] w4yltf */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Configure the behaviour of PuTTY's window",
@@ -1140,7 +1484,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == translationpanelstart) {
-       /* The Translation panel. Accelerators used: [acgo] rxbepus */
+       /* The Translation panel. Accelerators used: [acgoh] rxbepus */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling character set translation",
@@ -1168,7 +1512,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == selectionpanelstart) {
-       /* The Selection panel. Accelerators used: [acgo] df wxp hst nr */
+       /* The Selection panel. Accelerators used: [acgoh] df wxp est nr */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling copy and paste",
@@ -1199,14 +1543,14 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        endbox(&cp);
        beginbox(&cp, "Control the select-one-word-at-a-time mode",
                 IDC_BOX_SELECTION3);
-       charclass(&cp, "C&haracter classes:", IDC_CCSTATIC, IDC_CCLIST,
+       charclass(&cp, "Charact&er classes:", IDC_CCSTATIC, IDC_CCLIST,
                  "&Set", IDC_CCSET, IDC_CCEDIT,
                  "&to class", IDC_CCSTATIC2);
        endbox(&cp);
     }
 
     if (panel == colourspanelstart) {
-       /* The Colours panel. Accelerators used: [acgo] blum */
+       /* The Colours panel. Accelerators used: [acgoh] blum */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling use of colours",
@@ -1229,7 +1573,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == connectionpanelstart) {
-       /* The Connection panel. Accelerators used: [acgo] tukn */
+       /* The Connection panel. Accelerators used: [acgoh] tukn */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the connection",
@@ -1246,6 +1590,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            beginbox(&cp, "Adjust telnet session.", IDC_BOX_CONNECTION1);
            checkbox(&cp, "Keyboard sends telnet Backspace and Interrupt",
                     IDC_TELNETKEY);
+           checkbox(&cp, "Return key sends telnet New Line instead of ^M",
+                    IDC_TELNETRET);
            endbox(&cp);
        }
        beginbox(&cp, "Sending of null packets to keep session active",
@@ -1263,7 +1609,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == telnetpanelstart) {
-       /* The Telnet panel. Accelerators used: [acgo] svldr bftk */
+       /* The Telnet panel. Accelerators used: [acgoh] svldr bftk */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1286,12 +1632,14 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      IDC_TACTIVE, NULL);
            checkbox(&cp, "&Keyboard sends telnet Backspace and Interrupt",
                     IDC_TELNETKEY);
+           checkbox(&cp, "Return key sends telnet New Line instead of ^M",
+                    IDC_TELNETRET);
            endbox(&cp);
        }
     }
 
     if (panel == rloginpanelstart) {
-       /* The Rlogin panel. Accelerators used: [acgo] sl */
+       /* The Rlogin panel. Accelerators used: [acgoh] sl */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1307,7 +1655,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == sshpanelstart) {
-       /* The SSH panel. Accelerators used: [acgo] r pe12i sd */
+       /* The SSH panel. Accelerators used: [acgoh] r pe12i sd */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1338,7 +1686,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == sshauthpanelstart) {
-       /* The SSH authentication panel. Accelerators used: [acgo] m fkiw */
+       /* The SSH authentication panel. Accelerators used: [acgoh] m fkiuw */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1354,6 +1702,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            beginbox(&cp, "Authentication parameters",
                     IDC_BOX_SSHAUTH2);
            checkbox(&cp, "Allow agent &forwarding", IDC_AGENTFWD);
+           checkbox(&cp, "Allow attempted changes of &username in SSH2",
+                    IDC_CHANGEUSER);
            editbutton(&cp, "Private &key file for authentication:",
                       IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...",
                       IDC_PKBUTTON);
@@ -1362,7 +1712,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == tunnelspanelstart) {
-       /* The Tunnels panel. Accelerators used: [acgo] deilmrstx */
+       /* The Tunnels panel. Accelerators used: [acgoh] deilmrstxp */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1374,7 +1724,10 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      IDC_X11_DISPLAY, 50, NULL);
            endbox(&cp);
            beginbox(&cp, "Port forwarding", IDC_BOX_TUNNELS2);
-           checkbox(&cp, "Local ports accept connections from o&ther hosts", IDC_LPORT_ALL);
+           checkbox(&cp, "Local ports accept connections from o&ther hosts",
+                    IDC_LPORT_ALL);
+           checkbox(&cp, "Remote &ports do the same (SSH v2 only)",
+                    IDC_RPORT_ALL);
            staticbtn(&cp, "Forwarded ports:", IDC_PFWDSTATIC,
                      "&Remove", IDC_PFWDREMOVE);
            fwdsetter(&cp, IDC_PFWDLIST,
@@ -1383,7 +1736,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      "Dest&ination", IDC_DPORTSTATIC, IDC_DPORTEDIT,
                      "A&dd", IDC_PFWDADD);
            bareradioline(&cp, 2,
-                         "&Local", IDC_PFWDLOCAL, "Re&mote", IDC_PFWDREMOTE, NULL);
+                         "&Local", IDC_PFWDLOCAL,
+                         "Re&mote", IDC_PFWDREMOTE, NULL);
            endbox(&cp);
 
        }
@@ -1440,6 +1794,15 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
       case WM_INITDIALOG:
        readytogo = 0;
        SetWindowLong(hwnd, GWL_USERDATA, 0);
+        if (help_path)
+            SetWindowLong(hwnd, GWL_EXSTYLE,
+                          GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP);
+        else {
+            HWND item = GetDlgItem(hwnd, IDC_HELPBTN);
+            if (item)
+                DestroyWindow(item);
+        }
+        requested_help = FALSE;
        SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
                    (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(IDI_CFGICON)));
        /*
@@ -1636,12 +1999,31 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    }
                }
                /* If at this point we have a valid session, go! */
-               if (*cfg.host)
+               if (*cfg.host) {
+                    if (requested_help) {
+                        WinHelp(hwnd, help_path, HELP_QUIT, 0);
+                        requested_help = FALSE;
+                    }
                    EndDialog(hwnd, 1);
-               else
+                } else
                    MessageBeep(0);
                return 0;
+             case IDC_HELPBTN:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                    if (help_path) {
+                        WinHelp(hwnd, help_path,
+                                help_has_contents ? HELP_FINDER : HELP_CONTENTS,
+                                0);
+                        requested_help = TRUE;
+                    }
+                }
+                break;
              case IDCANCEL:
+                if (requested_help) {
+                    WinHelp(hwnd, help_path, HELP_QUIT, 0);
+                    requested_help = FALSE;
+                }
                EndDialog(hwnd, 0);
                return 0;
              case IDC_PROTTELNET:
@@ -1656,10 +2038,22 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    cfg.protocol =
                        i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN :
                        PROT_RAW;
-                   if ((cfg.protocol == PROT_SSH && cfg.port != 22)
-                       || (cfg.protocol == PROT_TELNET && cfg.port != 23)
-                       || (cfg.protocol == PROT_RLOGIN
-                           && cfg.port != 513)) {
+                   /*
+                    * When switching using the arrow keys, we
+                    * appear to get two of these messages, both
+                    * mentioning the target button in
+                    * LOWORD(wParam), but one of them called while
+                    * the previous button is still checked. This
+                    * causes an unnecessary reset of the port
+                    * number field, which we fix by ensuring here
+                    * that the button selected is indeed the one
+                    * checked.
+                    */
+                   if (IsDlgButtonChecked(hwnd, LOWORD(wParam)) &&
+                       ((cfg.protocol == PROT_SSH && cfg.port != 22)
+                        || (cfg.protocol == PROT_TELNET && cfg.port != 23)
+                        || (cfg.protocol == PROT_RLOGIN
+                            && cfg.port != 513))) {
                        cfg.port = i ? 22 : j ? 23 : 513;
                        SetDlgItemInt(hwnd, IDC_PORT, cfg.port, FALSE);
                    }
@@ -1965,6 +2359,12 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.telnet_keyboard =
                        IsDlgButtonChecked(hwnd, IDC_TELNETKEY);
                break;
+             case IDC_TELNETRET:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.telnet_newline =
+                       IsDlgButtonChecked(hwnd, IDC_TELNETRET);
+               break;
              case IDC_WRAPMODE:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -2254,14 +2654,17 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
              case IDC_LSTATOFF:
              case IDC_LSTATASCII:
              case IDC_LSTATRAW:
+             case IDC_LSTATPACKET:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED) {
                    if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF))
-                       cfg.logtype = 0;
+                       cfg.logtype = LGTYP_NONE;
                    if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII))
-                       cfg.logtype = 1;
+                       cfg.logtype = LGTYP_ASCII;
                    if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW))
-                       cfg.logtype = 2;
+                       cfg.logtype = LGTYP_DEBUG;
+                   if (IsDlgButtonChecked(hwnd, IDC_LSTATPACKET))
+                       cfg.logtype = LGTYP_PACKETS;
                }
                break;
              case IDC_LSTATXASK:
@@ -2408,6 +2811,12 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.agentfwd =
                        IsDlgButtonChecked(hwnd, IDC_AGENTFWD);
                break;
+             case IDC_CHANGEUSER:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.change_username =
+                       IsDlgButtonChecked(hwnd, IDC_CHANGEUSER);
+               break;
              case IDC_CIPHERLIST:
              case IDC_CIPHERUP:
              case IDC_CIPHERDN:
@@ -2638,14 +3047,20 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
              case IDC_X11_FORWARD:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
-                       cfg.x11_forward =
-                       IsDlgButtonChecked(hwnd, IDC_X11_FORWARD);
+                   cfg.x11_forward =
+                   IsDlgButtonChecked(hwnd, IDC_X11_FORWARD);
                break;
              case IDC_LPORT_ALL:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
-                       cfg.lport_acceptall =
-                       IsDlgButtonChecked(hwnd, IDC_LPORT_ALL);
+                   cfg.lport_acceptall =
+                   IsDlgButtonChecked(hwnd, IDC_LPORT_ALL);
+               break;
+             case IDC_RPORT_ALL:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                   cfg.rport_acceptall =
+                   IsDlgButtonChecked(hwnd, IDC_RPORT_ALL);
                break;
              case IDC_X11_DISPLAY:
                if (HIWORD(wParam) == EN_CHANGE)
@@ -2738,7 +3153,23 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                break;
            }
        return 0;
+      case WM_HELP:
+        if (help_path) {
+            int id = ((LPHELPINFO)lParam)->iCtrlId;
+            char *cmd = help_context_cmd(id);
+            if (cmd) {
+                WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
+                requested_help = TRUE;
+            } else {
+                MessageBeep(0);
+            }
+        }
+        break;
       case WM_CLOSE:
+        if (requested_help) {
+            WinHelp(hwnd, help_path, HELP_QUIT, 0);
+            requested_help = FALSE;
+        }
        EndDialog(hwnd, 0);
        return 0;
 
@@ -2934,7 +3365,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        if (mbret == IDYES)
            store_host_key(host, port, keytype, keystr);
        if (mbret == IDCANCEL)
-           exit(0);
+           cleanup_exit(0);
     }
     if (ret == 1) {                   /* key was absent */
        int mbret;
@@ -2944,7 +3375,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        if (mbret == IDYES)
            store_host_key(host, port, keytype, keystr);
        if (mbret == IDCANCEL)
-           exit(0);
+           cleanup_exit(0);
     }
 }
 
@@ -2975,7 +3406,7 @@ void askcipher(char *ciphername, int cs)
     if (mbret == IDYES)
        return;
     else
-       exit(0);
+       cleanup_exit(0);
 }
 
 /*