Justin Bradford's proxy support patch. Currently supports only HTTP
[u/mdw/putty] / windlg.c
index 2614457..f4a63de 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -27,6 +27,8 @@ static int requested_help;
 
 static struct prefslist cipherlist;
 
+#define PRINTER_DISABLED_STRING "None (printing disabled)"
+
 void force_normal(HWND hwnd)
 {
     static int recurse = 0;
@@ -296,8 +298,6 @@ enum { IDCX_ABOUT =
     IDC_KPNORMAL,
     IDC_KPAPPLIC,
     IDC_KPNH,
-    IDC_NOAPPLICK,
-    IDC_NOAPPLICC,
     IDC_CURSTATIC,
     IDC_CURNORMAL,
     IDC_CURAPPLIC,
@@ -309,6 +309,7 @@ enum { IDCX_ABOUT =
     IDC_TITLE_TERMINAL,
     IDC_BOX_TERMINAL1,
     IDC_BOX_TERMINAL2,
+    IDC_BOX_TERMINAL3,
     IDC_WRAPMODE,
     IDC_DECOM,
     IDC_LFHASCR,
@@ -324,8 +325,23 @@ enum { IDCX_ABOUT =
     IDC_EDITBACKEND,
     IDC_EDITYES,
     IDC_EDITNO,
+    IDC_PRINTERSTATIC,
+    IDC_PRINTER,
     terminalpanelend,
 
+    featurespanelstart,
+    IDC_TITLE_FEATURES,
+    IDC_BOX_FEATURES1,
+    IDC_NOAPPLICK,
+    IDC_NOAPPLICC,
+    IDC_NOMOUSEREP,
+    IDC_NORESIZE,
+    IDC_NOALTSCREEN,
+    IDC_NOWINTITLE,
+    IDC_NODBACKSPACE,
+    IDC_NOCHARSET,
+    featurespanelend,
+
     bellpanelstart,
     IDC_TITLE_BELL,
     IDC_BOX_BELL1,
@@ -422,6 +438,32 @@ enum { IDCX_ABOUT =
     IDC_NODELAY,
     connectionpanelend,
 
+    proxypanelstart,
+    IDC_TITLE_PROXY,
+    IDC_BOX_PROXY1,
+    IDC_PROXYTYPESTATIC,
+    IDC_PROXYTYPENONE,
+    IDC_PROXYTYPEHTTP,
+    IDC_PROXYTYPESOCKS,
+    IDC_PROXYTYPETELNET,
+    IDC_PROXYHOSTSTATIC,
+    IDC_PROXYHOSTEDIT,
+    IDC_PROXYPORTSTATIC,
+    IDC_PROXYPORTEDIT,
+    IDC_PROXYEXCLUDESTATIC,
+    IDC_PROXYEXCLUDEEDIT,
+    IDC_PROXYUSERSTATIC,
+    IDC_PROXYUSEREDIT,
+    IDC_PROXYPASSSTATIC,
+    IDC_PROXYPASSEDIT,
+    IDC_BOX_PROXY2,
+    IDC_PROXYTELNETCMDSTATIC,
+    IDC_PROXYTELNETCMDEDIT,
+    IDC_PROXYSOCKSVERSTATIC,
+    IDC_PROXYSOCKSVER5,
+    IDC_PROXYSOCKSVER4,
+    proxypanelend,
+
     telnetpanelstart,
     IDC_TITLE_TELNET,
     IDC_BOX_TELNET1,
@@ -662,9 +704,7 @@ char *help_context_cmd(int id)
       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:
@@ -676,6 +716,22 @@ char *help_context_cmd(int id)
       case IDC_CTRLALTKEYS:
         return "JI(`',`keyboard.ctrlalt')";
 
+      case IDC_NOAPPLICK:
+      case IDC_NOAPPLICC:
+        return "JI(`',`features.application')";
+      case IDC_NOMOUSEREP:
+        return "JI(`',`features.mouse')";
+      case IDC_NORESIZE:
+        return "JI(`',`features.resize')";
+      case IDC_NOALTSCREEN:
+        return "JI(`',`features.altscreen')";
+      case IDC_NOWINTITLE:
+        return "JI(`',`features.retitle')";
+      case IDC_NODBACKSPACE:
+        return "JI(`',`features.dbackspace')";
+      case IDC_NOCHARSET:
+        return "JI(`',`features.charset')";
+
       case IDC_WRAPMODE:
         return "JI(`',`terminal.autowrap')";
       case IDC_DECOM:
@@ -699,6 +755,9 @@ char *help_context_cmd(int id)
       case IDC_EDITYES:
       case IDC_EDITNO:
         return "JI(`',`terminal.localedit')";
+      case IDC_PRINTERSTATIC:
+      case IDC_PRINTER:
+       return "JI(`',`terminal.printing')";
 
       case IDC_BELLSTATIC:
       case IDC_BELL_DISABLED:
@@ -967,6 +1026,12 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
                     cfg.funky_type == 5 ? IDC_FUNCSCO : IDC_FUNCTILDE);
     CheckDlgButton(hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
     CheckDlgButton(hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
+    CheckDlgButton(hwnd, IDC_NOMOUSEREP, cfg.no_mouse_rep);
+    CheckDlgButton(hwnd, IDC_NORESIZE, cfg.no_remote_resize);
+    CheckDlgButton(hwnd, IDC_NOALTSCREEN, cfg.no_alt_screen);
+    CheckDlgButton(hwnd, IDC_NOWINTITLE, cfg.no_remote_wintitle);
+    CheckDlgButton(hwnd, IDC_NODBACKSPACE, cfg.no_dbackspace);
+    CheckDlgButton(hwnd, IDC_NOCHARSET, cfg.no_remote_charset);
     CheckRadioButton(hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
                     cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
     CheckRadioButton(hwnd, IDC_KPNORMAL, IDC_KPNH,
@@ -1172,7 +1237,25 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
        }
        SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
     }
-    
+
+    {
+       int i, nprinters;
+       printer_enum *pe;
+       pe = printer_start_enum(&nprinters);
+       strcpy(cfg.line_codepage, cp_name(decode_codepage(cfg.line_codepage)));
+       SendDlgItemMessage(hwnd, IDC_PRINTER, CB_RESETCONTENT, 0, 0);
+       SendDlgItemMessage(hwnd, IDC_PRINTER, CB_ADDSTRING,
+                          0, (LPARAM) PRINTER_DISABLED_STRING);
+       for (i = 0; i < nprinters; i++) {
+           char *printer_name = printer_get_name(pe, i);
+           SendDlgItemMessage(hwnd, IDC_PRINTER, CB_ADDSTRING,
+                              0, (LPARAM) printer_name);
+       }
+       printer_finish_enum(pe);
+       SetDlgItemText(hwnd, IDC_PRINTER,
+                      *cfg.printer ? cfg.printer : PRINTER_DISABLED_STRING);
+    }
+
     CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTUNICODE,
                     cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
                     cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
@@ -1186,6 +1269,20 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     CheckDlgButton(hwnd, IDC_LPORT_ALL, cfg.lport_acceptall);
     CheckDlgButton(hwnd, IDC_RPORT_ALL, cfg.rport_acceptall);
     CheckRadioButton(hwnd, IDC_PFWDLOCAL, IDC_PFWDREMOTE, IDC_PFWDLOCAL);
+
+    /* proxy config */
+    CheckRadioButton(hwnd, IDC_PROXYTYPENONE, IDC_PROXYTYPETELNET,
+                    cfg.proxy_type == PROXY_HTTP ? IDC_PROXYTYPEHTTP :
+                    cfg.proxy_type == PROXY_SOCKS ? IDC_PROXYTYPESOCKS :
+                    cfg.proxy_type == PROXY_TELNET ? IDC_PROXYTYPETELNET : IDC_PROXYTYPENONE);
+    SetDlgItemText(hwnd, IDC_PROXYHOSTEDIT, cfg.proxy_host);
+    SetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, cfg.proxy_port, FALSE);
+    SetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT, cfg.proxy_exclude_list);
+    SetDlgItemText(hwnd, IDC_PROXYTELNETCMDEDIT, cfg.proxy_telnet_command);
+    SetDlgItemText(hwnd, IDC_PROXYUSEREDIT, cfg.proxy_username);
+    SetDlgItemText(hwnd, IDC_PROXYPASSEDIT, cfg.proxy_password);
+    CheckRadioButton(hwnd, IDC_PROXYSOCKSVER5, IDC_PROXYSOCKSVER4,
+                    cfg.proxy_socks_version == 4 ? IDC_PROXYSOCKSVER4 : IDC_PROXYSOCKSVER5);
 }
 
 struct treeview_faff {
@@ -1224,7 +1321,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",
@@ -1248,9 +1345,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);
            }
@@ -1260,7 +1357,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);
@@ -1272,7 +1369,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == loggingpanelstart) {
-       /* The Logging panel. Accelerators used: [acgo] tplsfwe */
+       /* The Logging panel. Accelerators used: [acgoh] tplsfwe */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling session logging",
@@ -1299,7 +1396,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 p */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the terminal emulation",
@@ -1307,7 +1404,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,
@@ -1316,17 +1413,45 @@ 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,
                  "Auto", IDC_EDITBACKEND,
                  "Force on", IDC_EDITYES, "Force off", IDC_EDITNO, NULL);
        endbox(&cp);
+
+       beginbox(&cp, "Remote-controlled printing", IDC_BOX_TERMINAL3);
+       combobox(&cp, "&Printer to send ANSI printer output to:",
+                IDC_PRINTERSTATIC, IDC_PRINTER);
+       endbox(&cp);
+    }
+
+    if (panel == featurespanelstart) {
+       /* The Features panel. Accelerators used: [acgoh] ukswtbrx */
+       struct ctlpos cp;
+       ctlposinit(&cp, hwnd, 80, 3, 13);
+       bartitle(&cp, "Enabling and disabling advanced terminal features ",
+                IDC_TITLE_FEATURES);
+       beginbox(&cp, NULL, IDC_BOX_FEATURES1);
+       checkbox(&cp, "Disable application c&ursor keys mode", IDC_NOAPPLICC);
+       checkbox(&cp, "Disable application &keypad mode", IDC_NOAPPLICK);
+       checkbox(&cp, "Disable &xterm-style mouse reporting", IDC_NOMOUSEREP);
+       checkbox(&cp, "Disable remote-controlled terminal re&sizing",
+                IDC_NORESIZE);
+       checkbox(&cp, "Disable s&witching to alternate terminal screen",
+                IDC_NOALTSCREEN);
+       checkbox(&cp, "Disable remote-controlled window &title changing",
+                IDC_NOWINTITLE);
+       checkbox(&cp, "Disable destructive &backspace on server sending ^?",
+                IDC_NODBACKSPACE);
+       checkbox(&cp, "Disable remote-controlled cha&racter set configuration",
+                IDC_NOCHARSET);
+       endbox(&cp);
     }
 
     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",
@@ -1363,7 +1488,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 rntd */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the effects of keys",
@@ -1372,7 +1497,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,
@@ -1382,15 +1507,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                  "VT100+", IDC_FUNCVT100P, "SCO", IDC_FUNCSCO, NULL);
        endbox(&cp);
        beginbox(&cp, "Application keypad settings:", IDC_BOX_KEYBOARD2);
-       checkbox(&cp,
-                "Application c&ursor keys totally disabled",
-                IDC_NOAPPLICC);
        radioline(&cp, "Initial state of cu&rsor keys:", IDC_CURSTATIC, 2,
                  "Normal", IDC_CURNORMAL,
                  "Application", IDC_CURAPPLIC, NULL);
-       checkbox(&cp,
-                "Application ke&ypad keys totally disabled",
-                IDC_NOAPPLICK);
        radioline(&cp, "Initial state of &numeric keypad:", IDC_KPSTATIC,
                  3, "Normal", IDC_KPNORMAL, "Application", IDC_KPAPPLIC,
                  "NetHack", IDC_KPNH, NULL);
@@ -1404,7 +1523,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",
@@ -1432,7 +1551,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",
@@ -1446,7 +1565,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);
@@ -1468,7 +1587,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",
@@ -1484,7 +1603,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",
@@ -1512,7 +1631,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",
@@ -1543,14 +1662,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",
@@ -1573,7 +1692,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",
@@ -1608,8 +1727,43 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        }
     }
 
+    if (panel == proxypanelstart) {
+       /* The Proxy panel. Accelerators used: [acgoh] ntslypeuwmv */
+       struct ctlpos cp;
+       ctlposinit(&cp, hwnd, 80, 3, 13);
+       if (dlgtype == 0) {
+           bartitle(&cp, "Options controlling proxy usage",
+                    IDC_TITLE_PROXY);
+           beginbox(&cp, "Proxy basics", IDC_BOX_PROXY1);
+           radioline(&cp, "Proxy type:", IDC_PROXYTYPESTATIC, 4,
+                     "&None", IDC_PROXYTYPENONE,
+                     "H&TTP", IDC_PROXYTYPEHTTP,
+                     "&SOCKS", IDC_PROXYTYPESOCKS,
+                     "Te&lnet", IDC_PROXYTYPETELNET, NULL);
+           multiedit(&cp,
+                     "Prox&y Host", IDC_PROXYHOSTSTATIC, IDC_PROXYHOSTEDIT, 80,
+                     "&Port", IDC_PROXYPORTSTATIC, IDC_PROXYPORTEDIT, 20, NULL);
+           multiedit(&cp,
+                     "&Exclude Hosts/IPs", IDC_PROXYEXCLUDESTATIC,
+                     IDC_PROXYEXCLUDEEDIT, 100, NULL);
+           staticedit(&cp, "&Username", IDC_PROXYUSERSTATIC,
+                      IDC_PROXYUSEREDIT, 60);
+           staticedit(&cp, "Pass&word", IDC_PROXYPASSSTATIC,
+                      IDC_PROXYPASSEDIT, 60);
+           endbox(&cp);
+           beginbox(&cp, "Misc. proxy settings", IDC_BOX_PROXY2);
+           multiedit(&cp,
+                     "Telnet co&mmand", IDC_PROXYTELNETCMDSTATIC,
+                     IDC_PROXYTELNETCMDEDIT, 100, NULL);
+           radioline(&cp, "SOCKS &Version", IDC_PROXYSOCKSVERSTATIC,
+                     2, "Version 5", IDC_PROXYSOCKSVER5, "Version 4",
+                     IDC_PROXYSOCKSVER4, NULL);
+           endbox(&cp);
+       }
+    }
+
     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) {
@@ -1639,7 +1793,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     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) {
@@ -1655,7 +1809,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) {
@@ -1686,7 +1840,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == sshauthpanelstart) {
-       /* The SSH authentication panel. Accelerators used: [acgo] m fkiuw */
+       /* The SSH authentication panel. Accelerators used: [acgoh] m fkiuw */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1712,7 +1866,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == tunnelspanelstart) {
-       /* The Tunnels panel. Accelerators used: [acgo] deilmrsthx */
+       /* The Tunnels panel. Accelerators used: [acgoh] deilmrstxp */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1726,7 +1880,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            beginbox(&cp, "Port forwarding", IDC_BOX_TUNNELS2);
            checkbox(&cp, "Local ports accept connections from o&ther hosts",
                     IDC_LPORT_ALL);
-           checkbox(&cp, "Remote ports do t&he same (SSH v2 only)",
+           checkbox(&cp, "Remote &ports do the same (SSH v2 only)",
                     IDC_RPORT_ALL);
            staticbtn(&cp, "Forwarded ports:", IDC_PFWDSTATIC,
                      "&Remove", IDC_PFWDREMOVE);
@@ -1869,6 +2023,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        treeview_insert(&tvfaff, 0, "Terminal");
        treeview_insert(&tvfaff, 1, "Keyboard");
        treeview_insert(&tvfaff, 1, "Bell");
+       treeview_insert(&tvfaff, 1, "Features");
        treeview_insert(&tvfaff, 0, "Window");
        treeview_insert(&tvfaff, 1, "Appearance");
        treeview_insert(&tvfaff, 1, "Behaviour");
@@ -1877,6 +2032,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        treeview_insert(&tvfaff, 1, "Colours");
        treeview_insert(&tvfaff, 0, "Connection");
        if (dlgtype == 0) {
+           treeview_insert(&tvfaff, 1, "Proxy");
            treeview_insert(&tvfaff, 1, "Telnet");
            treeview_insert(&tvfaff, 1, "Rlogin");
            if (backends[3].backend != NULL) {
@@ -1948,6 +2104,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                create_controls(hwnd, dlgtype, terminalpanelstart);
            if (!strcmp(buffer, "Bell"))
                create_controls(hwnd, dlgtype, bellpanelstart);
+           if (!strcmp(buffer, "Features"))
+               create_controls(hwnd, dlgtype, featurespanelstart);
            if (!strcmp(buffer, "Window"))
                create_controls(hwnd, dlgtype, windowpanelstart);
            if (!strcmp(buffer, "Appearance"))
@@ -1958,6 +2116,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                create_controls(hwnd, dlgtype, tunnelspanelstart);
            if (!strcmp(buffer, "Connection"))
                create_controls(hwnd, dlgtype, connectionpanelstart);
+           if (!strcmp(buffer, "Proxy"))
+               create_controls(hwnd, dlgtype, proxypanelstart);
            if (!strcmp(buffer, "Telnet"))
                create_controls(hwnd, dlgtype, telnetpanelstart);
            if (!strcmp(buffer, "Rlogin"))
@@ -2038,10 +2198,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);
                    }
@@ -2257,6 +2429,42 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.no_applic_k =
                        IsDlgButtonChecked(hwnd, IDC_NOAPPLICK);
                break;
+             case IDC_NOMOUSEREP:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_mouse_rep =
+                       IsDlgButtonChecked(hwnd, IDC_NOMOUSEREP);
+               break;
+             case IDC_NORESIZE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_remote_resize =
+                       IsDlgButtonChecked(hwnd, IDC_NORESIZE);
+               break;
+             case IDC_NOALTSCREEN:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_alt_screen =
+                       IsDlgButtonChecked(hwnd, IDC_NOALTSCREEN);
+               break;
+             case IDC_NOWINTITLE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_remote_wintitle =
+                       IsDlgButtonChecked(hwnd, IDC_NOWINTITLE);
+               break;
+             case IDC_NODBACKSPACE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_dbackspace =
+                       IsDlgButtonChecked(hwnd, IDC_NODBACKSPACE);
+               break;
+             case IDC_NOCHARSET:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_remote_charset =
+                       IsDlgButtonChecked(hwnd, IDC_NOCHARSET);
+               break;
              case IDC_ALTF4:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -2611,6 +2819,73 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    GetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype,
                                   sizeof(cfg.termtype) - 1);
                break;
+
+               /* proxy config */
+             case IDC_PROXYHOSTEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYHOSTEDIT, cfg.proxy_host, 
+                                  sizeof(cfg.proxy_host) - 1);
+               break;
+             case IDC_PROXYPORTEDIT:
+               if (HIWORD(wParam) == EN_CHANGE) {
+                   GetDlgItemText(hwnd, IDC_PROXYPORTEDIT, portname, 31);
+                   if (isdigit(portname[0]))
+                       MyGetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, &cfg.proxy_port);
+                   else {
+                       service = getservbyname(portname, NULL);
+                       if (service)
+                           cfg.proxy_port = ntohs(service->s_port);
+                       else
+                           cfg.proxy_port = 0;
+                   }
+               }
+               break;
+             case IDC_PROXYEXCLUDEEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT,
+                                  cfg.proxy_exclude_list,
+                                  sizeof(cfg.proxy_exclude_list) - 1);
+               break;
+             case IDC_PROXYUSEREDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYUSEREDIT,
+                                  cfg.proxy_username, 
+                                  sizeof(cfg.proxy_username) - 1);
+               break;
+             case IDC_PROXYPASSEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYPASSEDIT,
+                                  cfg.proxy_password, 
+                                  sizeof(cfg.proxy_password) - 1);
+               break;
+             case IDC_PROXYTELNETCMDEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYTELNETCMDEDIT,
+                                  cfg.proxy_telnet_command,
+                                  sizeof(cfg.proxy_telnet_command) - 1);
+               break;
+             case IDC_PROXYSOCKSVER5:
+             case IDC_PROXYSOCKSVER4:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   cfg.proxy_socks_version =
+                       IsDlgButtonChecked(hwnd, IDC_PROXYSOCKSVER4) ? 4 : 5;
+               }
+               break;
+             case IDC_PROXYTYPENONE:
+             case IDC_PROXYTYPEHTTP:
+             case IDC_PROXYTYPESOCKS:
+             case IDC_PROXYTYPETELNET:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   cfg.proxy_type =
+                       IsDlgButtonChecked(hwnd, IDC_PROXYTYPEHTTP) ? PROXY_HTTP :
+                       IsDlgButtonChecked(hwnd, IDC_PROXYTYPESOCKS) ? PROXY_SOCKS :
+                       IsDlgButtonChecked(hwnd, IDC_PROXYTYPETELNET) ? PROXY_TELNET :
+                       PROXY_NONE;
+               }
+               break;
+
              case IDC_LGFEDIT:
                if (HIWORD(wParam) == EN_CHANGE)
                    GetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename,
@@ -3010,6 +3285,19 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
                }
                break;
+             case IDC_PRINTER:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_PRINTER,
+                                                  CB_GETCURSEL, 0, 0);
+                   SendDlgItemMessage(hwnd, IDC_PRINTER, CB_GETLBTEXT,
+                                      index, (LPARAM)cfg.printer);
+               } else if (HIWORD(wParam) == CBN_EDITCHANGE) {
+                   GetDlgItemText(hwnd, IDC_PRINTER, cfg.printer,
+                                  sizeof(cfg.printer) - 1);
+               }
+               if (!strcmp(cfg.printer, PRINTER_DISABLED_STRING))
+                   *cfg.printer = '\0';
+               break;
              case IDC_CAPSLOCKCYR:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED) {
@@ -3353,7 +3641,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;
@@ -3363,7 +3651,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);
     }
 }
 
@@ -3394,7 +3682,7 @@ void askcipher(char *ciphername, int cs)
     if (mbret == IDYES)
        return;
     else
-       exit(0);
+       cleanup_exit(0);
 }
 
 /*