Comment/string tweaks to reflect new DES-in-SSH2 capability.
[u/mdw/putty] / windlg.c
index 2f9ca56..cb4b2b5 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -16,6 +16,9 @@ static char **events = NULL;
 static int nevents = 0, negsize = 0;
 
 static int readytogo;
+static int sesslist_has_focus;
+
+static struct prefslist cipherlist;
 
 void force_normal(HWND hwnd)
 {
@@ -128,7 +131,7 @@ static int CALLBACK LogProc(HWND hwnd, UINT msg,
                            memcpy(p, sel_nl, sizeof(sel_nl));
                            p += sizeof(sel_nl);
                        }
-                       write_clip(clipdata, size, TRUE);
+                       write_aclip(clipdata, size, TRUE);
                        sfree(clipdata);
                    }
                    sfree(selitems);
@@ -256,6 +259,7 @@ enum { IDCX_ABOUT =
     IDC_LGFSTATIC,
     IDC_LGFEDIT,
     IDC_LGFBUTTON,
+    IDC_LGFEXPLAIN,
     IDC_LSTATXIST,
     IDC_LSTATXOVR,
     IDC_LSTATXAPN,
@@ -327,6 +331,10 @@ enum { IDCX_ABOUT =
     IDC_BELL_WAVESTATIC,
     IDC_BELL_WAVEEDIT,
     IDC_BELL_WAVEBROWSE,
+    IDC_B_IND_STATIC,
+    IDC_B_IND_DISABLED,
+    IDC_B_IND_FLASH,
+    IDC_B_IND_STEADY,
     IDC_BELLOVL,
     IDC_BELLOVLNSTATIC,
     IDC_BELLOVLN,
@@ -346,8 +354,12 @@ enum { IDCX_ABOUT =
     IDC_ROWSEDIT,
     IDC_COLSSTATIC,
     IDC_COLSEDIT,
-    IDC_LOCKSIZE,
+    IDC_RESIZESTATIC,
+    IDC_RESIZETERM,
+    IDC_RESIZEFONT,
+    IDC_RESIZENONE,
     IDC_SCROLLBAR,
+    IDC_SCROLLBARFULLSCREEN,
     IDC_CLOSEWARN,
     IDC_SAVESTATIC,
     IDC_SAVEEDIT,
@@ -357,6 +369,7 @@ enum { IDCX_ABOUT =
     IDC_SCROLLKEY,
     IDC_SCROLLDISP,
     IDC_ALWAYSONTOP,
+    IDC_FULLSCREENONALTENTER,
     windowpanelend,
 
     appearancepanelstart,
@@ -378,6 +391,8 @@ enum { IDCX_ABOUT =
     IDC_WINNAME,
     IDC_HIDEMOUSE,
     IDC_SUNKENEDGE,
+    IDC_WINBSTATIC,
+    IDC_WINBEDIT,
     appearancepanelend,
 
     connectionpanelstart,
@@ -430,25 +445,31 @@ enum { IDCX_ABOUT =
     IDC_BOX_SSH2,
     IDC_BOX_SSH3,
     IDC_NOPTY,
-    IDC_CIPHERSTATIC,
-    IDC_CIPHER3DES,
-    IDC_CIPHERBLOWF,
-    IDC_CIPHERDES,
-    IDC_CIPHERAES,
+    IDC_BOX_SSHCIPHER,
+    IDC_CIPHERSTATIC2,
+    IDC_CIPHERLIST,
+    IDC_CIPHERUP,
+    IDC_CIPHERDN,
     IDC_BUGGYMAC,
-    IDC_AUTHTIS,
-    IDC_PKSTATIC,
-    IDC_PKEDIT,
-    IDC_PKBUTTON,
     IDC_SSHPROTSTATIC,
     IDC_SSHPROT1,
     IDC_SSHPROT2,
-    IDC_AGENTFWD,
     IDC_CMDSTATIC,
     IDC_CMDEDIT,
     IDC_COMPRESS,
     sshpanelend,
 
+    sshauthpanelstart,
+    IDC_TITLE_SSHAUTH,
+    IDC_BOX_SSHAUTH1,
+    IDC_BOX_SSHAUTH2,
+    IDC_PKSTATIC,
+    IDC_PKEDIT,
+    IDC_PKBUTTON,
+    IDC_AGENTFWD,
+    IDC_AUTHTIS,
+    sshauthpanelend,
+
     selectionpanelstart,
     IDC_TITLE_SELECTION,
     IDC_BOX_SELECTION1,
@@ -457,12 +478,17 @@ enum { IDCX_ABOUT =
     IDC_MBSTATIC,
     IDC_MBWINDOWS,
     IDC_MBXTERM,
+    IDC_MOUSEOVERRIDE,
+    IDC_SELTYPESTATIC,
+    IDC_SELTYPELEX,
+    IDC_SELTYPERECT,
     IDC_CCSTATIC,
     IDC_CCLIST,
     IDC_CCSET,
     IDC_CCSTATIC2,
     IDC_CCEDIT,
     IDC_RAWCNP,
+    IDC_RTFPASTE,
     selectionpanelend,
 
     colourspanelstart,
@@ -487,25 +513,37 @@ enum { IDCX_ABOUT =
     IDC_BOX_TRANSLATION1,
     IDC_BOX_TRANSLATION2,
     IDC_BOX_TRANSLATION3,
-    IDC_XLATSTATIC,
-    IDC_NOXLAT,
-    IDC_KOI8WIN1251,
-    IDC_88592WIN1250,
-    IDC_88592CP852,
+    IDC_CODEPAGESTATIC,
+    IDC_CODEPAGE,
     IDC_CAPSLOCKCYR,
     IDC_VTSTATIC,
     IDC_VTXWINDOWS,
     IDC_VTOEMANSI,
     IDC_VTOEMONLY,
     IDC_VTPOORMAN,
+    IDC_VTUNICODE,
     translationpanelend,
 
     tunnelspanelstart,
     IDC_TITLE_TUNNELS,
-    IDC_BOX_TUNNELS,
+    IDC_BOX_TUNNELS1,
+    IDC_BOX_TUNNELS2,
     IDC_X11_FORWARD,
     IDC_X11_DISPSTATIC,
     IDC_X11_DISPLAY,
+    IDC_LPORT_ALL,
+    IDC_PFWDSTATIC,
+    IDC_PFWDSTATIC2,
+    IDC_PFWDREMOVE,
+    IDC_PFWDLIST,
+    IDC_PFWDADD,
+    IDC_SPORTSTATIC,
+    IDC_SPORTEDIT,
+    IDC_DPORTSTATIC,
+    IDC_DPORTEDIT,
+    IDC_PFWDLOCAL,
+    IDC_PFWDREMOTE,
+
     tunnelspanelend,
 
     controlendvalue
@@ -542,14 +580,16 @@ static void fmtfont(char *buf)
                (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight));
 }
 
-static void init_dlg_ctrls(HWND hwnd)
+/* 2nd arg: NZ => don't redraw session list (use when loading
+ * a new session) */
+static void init_dlg_ctrls(HWND hwnd, int keepsess)
 {
     int i;
     char fontstatic[256];
 
     SetDlgItemText(hwnd, IDC_HOST, cfg.host);
     SetDlgItemText(hwnd, IDC_SESSEDIT, savedsession);
-    {
+    if (!keepsess) {
        int i, n;
        n = SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_GETCOUNT, 0, 0);
        for (i = n; i-- > 0;)
@@ -598,6 +638,7 @@ static void init_dlg_ctrls(HWND hwnd)
                     cfg.localedit == LD_YES ? IDC_EDITYES : IDC_EDITNO);
     SetDlgItemText(hwnd, IDC_ANSWEREDIT, cfg.answerback);
     CheckDlgButton(hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
+    CheckDlgButton(hwnd, IDC_FULLSCREENONALTENTER, cfg.fullscreenonaltenter);
     CheckDlgButton(hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
     CheckDlgButton(hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
 
@@ -615,6 +656,11 @@ static void init_dlg_ctrls(HWND hwnd)
                     cfg.beep == BELL_WAVEFILE ? IDC_BELL_WAVEFILE :
                     cfg.beep ==
                     BELL_VISUAL ? IDC_BELL_VISUAL : IDC_BELL_DEFAULT);
+    CheckRadioButton(hwnd, IDC_B_IND_DISABLED, IDC_B_IND_STEADY,
+                    cfg.beep_ind ==
+                    B_IND_DISABLED ? IDC_B_IND_DISABLED : cfg.beep_ind ==
+                    B_IND_FLASH ? IDC_B_IND_FLASH : cfg.beep_ind ==
+                    B_IND_STEADY ? IDC_B_IND_STEADY : IDC_B_IND_DISABLED);
     SetDlgItemText(hwnd, IDC_BELL_WAVEEDIT, cfg.bell_wavefile);
     CheckDlgButton(hwnd, IDC_BELLOVL, cfg.bellovl);
     SetDlgItemInt(hwnd, IDC_BELLOVLN, cfg.bellovl_n, FALSE);
@@ -628,12 +674,17 @@ static void init_dlg_ctrls(HWND hwnd)
     CheckDlgButton(hwnd, IDC_WINNAME, cfg.win_name_always);
     CheckDlgButton(hwnd, IDC_HIDEMOUSE, cfg.hide_mouseptr);
     CheckDlgButton(hwnd, IDC_SUNKENEDGE, cfg.sunken_edge);
+    SetDlgItemInt(hwnd, IDC_WINBEDIT, cfg.window_border, FALSE);
     CheckRadioButton(hwnd, IDC_CURBLOCK, IDC_CURVERT,
                     cfg.cursor_type == 0 ? IDC_CURBLOCK :
                     cfg.cursor_type == 1 ? IDC_CURUNDER : IDC_CURVERT);
     CheckDlgButton(hwnd, IDC_BLINKCUR, cfg.blink_cur);
     CheckDlgButton(hwnd, IDC_SCROLLBAR, cfg.scrollbar);
-    CheckDlgButton(hwnd, IDC_LOCKSIZE, cfg.locksize);
+    CheckDlgButton(hwnd, IDC_SCROLLBARFULLSCREEN, cfg.scrollbar_in_fullscreen);
+    CheckRadioButton(hwnd, IDC_RESIZETERM, IDC_RESIZENONE,
+                    cfg.resize_action == RESIZE_TERM ? IDC_RESIZETERM :
+                    cfg.resize_action == RESIZE_FONT ? IDC_RESIZEFONT :
+                    IDC_RESIZENONE);
     CheckRadioButton(hwnd, IDC_COEALWAYS, IDC_COENORMAL,
                     cfg.close_on_exit == COE_NORMAL ? IDC_COENORMAL :
                     cfg.close_on_exit ==
@@ -655,11 +706,18 @@ static void init_dlg_ctrls(HWND hwnd)
                     IDC_LSTATXAPN);
     {
        char *p = cfg.environmt;
+       SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_RESETCONTENT, 0, 0);
        while (*p) {
            SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
                               (LPARAM) p);
            p += strlen(p) + 1;
        }
+       p = cfg.portfwd;
+       while (*p) {
+           SendDlgItemMessage(hwnd, IDC_PFWDLIST, LB_ADDSTRING, 0,
+                              (LPARAM) p);
+           p += strlen(p) + 1;
+       }
     }
     CheckRadioButton(hwnd, IDC_EMBSD, IDC_EMRFC,
                     cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
@@ -672,26 +730,56 @@ static void init_dlg_ctrls(HWND hwnd)
     CheckDlgButton(hwnd, IDC_COMPRESS, cfg.compression);
     CheckDlgButton(hwnd, IDC_BUGGYMAC, cfg.buggymac);
     CheckDlgButton(hwnd, IDC_AGENTFWD, cfg.agentfwd);
-    CheckRadioButton(hwnd, IDC_CIPHER3DES, IDC_CIPHERAES,
-                    cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
-                    cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
-                    cfg.cipher == CIPHER_AES ? IDC_CIPHERAES :
-                    IDC_CIPHER3DES);
     CheckRadioButton(hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
                     cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
     CheckDlgButton(hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
     SetDlgItemText(hwnd, IDC_CMDEDIT, cfg.remote_cmd);
 
+    {
+       int i;
+       static const struct { char *s; int c; } ciphers[] = {
+           { "3DES",                   CIPHER_3DES },
+           { "Blowfish",               CIPHER_BLOWFISH },
+           { "DES",                    CIPHER_DES },
+           { "AES (SSH 2 only)",       CIPHER_AES },
+           { "-- warn below here --",  CIPHER_WARN }
+       };
+
+       /* Set up the "selected ciphers" box. */
+       /* (cipherlist assumed to contain all ciphers) */
+       SendDlgItemMessage(hwnd, IDC_CIPHERLIST, LB_RESETCONTENT, 0, 0);
+       for (i = 0; i < CIPHER_MAX; i++) {
+           int c = cfg.ssh_cipherlist[i];
+           int j, pos;
+           char *cstr = NULL;
+           for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) {
+               if (ciphers[j].c == c) {
+                   cstr = ciphers[j].s;
+                   break;
+               }
+           }
+           pos = SendDlgItemMessage(hwnd, IDC_CIPHERLIST, LB_ADDSTRING,
+                                    0, (LPARAM) cstr);
+           SendDlgItemMessage(hwnd, IDC_CIPHERLIST, LB_SETITEMDATA,
+                              pos, (LPARAM) c);
+       }
+
+    }
+
     CheckRadioButton(hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
                     cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
+    CheckRadioButton(hwnd, IDC_SELTYPELEX, IDC_SELTYPERECT,
+                    cfg.rect_select == 0 ? IDC_SELTYPELEX : IDC_SELTYPERECT);
+    CheckDlgButton(hwnd, IDC_MOUSEOVERRIDE, cfg.mouse_override);
     CheckDlgButton(hwnd, IDC_RAWCNP, cfg.rawcnp);
+    CheckDlgButton(hwnd, IDC_RTFPASTE, cfg.rtf_paste);
     {
        static int tabs[4] = { 25, 61, 96, 128 };
        SendDlgItemMessage(hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
                           (LPARAM) tabs);
     }
-    for (i = 0; i < 256; i++) {
+    for (i = 0; i < 128; i++) {
        char str[100];
        sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
                (i >= 0x21 && i != 0x7F) ? i : ' ', cfg.wordness[i]);
@@ -717,19 +805,31 @@ static void init_dlg_ctrls(HWND hwnd)
     SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
     SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
 
-    CheckRadioButton(hwnd, IDC_NOXLAT, IDC_88592CP852,
-                    cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
-                    cfg.xlat_88592cp852 ? IDC_88592CP852 :
-                    cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 : IDC_NOXLAT);
-    CheckDlgButton(hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
-    CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
+    {
+       int i;
+       char *cp;
+       strcpy(cfg.line_codepage, cp_name(decode_codepage(cfg.line_codepage)));
+       SendDlgItemMessage(hwnd, IDC_CODEPAGE, CB_RESETCONTENT, 0, 0);
+       CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
+       for (i = 0; (cp = cp_enumerate(i)) != NULL; i++) {
+           SendDlgItemMessage(hwnd, IDC_CODEPAGE, CB_ADDSTRING,
+                              0, (LPARAM) cp);
+       }
+       SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
+    }
+    
+    CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTUNICODE,
                     cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
                     cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
                     cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
+                    cfg.vtmode == VT_UNICODE ? IDC_VTUNICODE :
                     IDC_VTPOORMAN);
 
     CheckDlgButton(hwnd, IDC_X11_FORWARD, cfg.x11_forward);
     SetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display);
+
+    CheckDlgButton(hwnd, IDC_LPORT_ALL, cfg.lport_acceptall);
+    CheckRadioButton(hwnd, IDC_PFWDLOCAL, IDC_PFWDREMOTE, IDC_PFWDLOCAL);
 }
 
 struct treeview_faff {
@@ -774,14 +874,15 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        bartitle(&cp, "Basic options for your PuTTY session",
                 IDC_TITLE_SESSION);
        if (dlgtype == 0) {
-           beginbox(&cp, "Specify your connection by host name",
+           beginbox(&cp, "Specify your connection by host name or IP address",
                     IDC_BOX_SESSION1);
            multiedit(&cp,
-                     "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
+                     "Host &Name (or IP address)",
+                     IDC_HOSTSTATIC, IDC_HOST, 75,
                      "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
            if (backends[3].backend == NULL) {
                /* this is PuTTYtel, so only three protocols available */
-               radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
+               radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
                          "&Raw", IDC_PROTRAW,
                          "&Telnet", IDC_PROTTELNET,
                          "Rlog&in", IDC_PROTRLOGIN, NULL);
@@ -829,6 +930,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        editbutton(&cp, "Log &file name:",
                   IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
                   IDC_LGFBUTTON);
+       statictext(&cp, "(Log file name can contain &&Y, &&M, &&D for date,"
+                  " &&T for time, and &&H for host name)", 2, IDC_LGFEXPLAIN);
        radiobig(&cp,
                 "What to do if the log file already &exists:",
                 IDC_LSTATXIST, "Always overwrite it", IDC_LSTATXOVR,
@@ -865,7 +968,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == bellpanelstart) {
-       /* The Bell panel. Accelerators used: [acgo] bdsm wt */
+       /* The Bell panel. Accelerators used: [acgo] bdsm wit */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the terminal bell",
@@ -880,6 +983,10 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        editbutton(&cp, "Custom sound file to play as a bell:",
                   IDC_BELL_WAVESTATIC, IDC_BELL_WAVEEDIT,
                   "Bro&wse...", IDC_BELL_WAVEBROWSE);
+       radioline(&cp, "Taskbar/caption &indication on bell:",
+                 IDC_B_IND_STATIC, 3, "Disabled", IDC_B_IND_DISABLED,
+                 "Flashing", IDC_B_IND_FLASH, "Steady", IDC_B_IND_STEADY,
+                 NULL);
        endbox(&cp);
        beginbox(&cp, "Control the bell overload behaviour",
                 IDC_BOX_BELL2);
@@ -891,7 +998,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                   IDC_BELLOVLTSTATIC, IDC_BELLOVLT, 20);
        statictext(&cp,
                   "The bell is re-enabled after a few seconds of silence.",
-                  IDC_BELLOVLEXPLAIN);
+                  1, IDC_BELLOVLEXPLAIN);
        staticedit(&cp, "Seconds of &silence required", IDC_BELLOVLSSTATIC,
                   IDC_BELLOVLS, 20);
        endbox(&cp);
@@ -941,7 +1048,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == windowpanelstart) {
-       /* The Window panel. Accelerators used: [acgo] rmz sdkp w4ylt */
+       /* The Window panel. Accelerators used: [acgo] rmznb sdikp w4ylt f */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling PuTTY's window",
@@ -950,13 +1057,17 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        multiedit(&cp,
                  "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
                  "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50, NULL);
-       checkbox(&cp, "Lock window size against resi&zing", IDC_LOCKSIZE);
+       radioline(&cp, "Action when the window is resized:", IDC_RESIZESTATIC,
+                 3, "Resi&ze terminal", IDC_RESIZETERM,
+                 "Change fo&nt", IDC_RESIZEFONT,
+                 "For&bid resizing", IDC_RESIZENONE, NULL);
        endbox(&cp);
        beginbox(&cp, "Control the scrollback in the window",
                 IDC_BOX_WINDOW2);
        staticedit(&cp, "Lines of &scrollback",
                   IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
        checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
+       checkbox(&cp, "D&isplay scrollbar in full screen mode", IDC_SCROLLBARFULLSCREEN);
        checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
        checkbox(&cp, "Reset scrollback on dis&play activity",
                 IDC_SCROLLDISP);
@@ -967,6 +1078,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
        checkbox(&cp, "System menu appears on A&LT alone", IDC_ALTONLY);
        checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
+       checkbox(&cp, "&Full screen on Alt-Enter", IDC_FULLSCREENONALTENTER);
        endbox(&cp);
     }
 
@@ -974,8 +1086,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        /* The Appearance panel. Accelerators used: [acgo] luvb h ti p s */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
-       bartitle(&cp, "Options controlling PuTTY's appearance",
-                IDC_TITLE_APPEARANCE);
+       /* bartitle(&cp, "Options controlling PuTTY's appearance",
+                IDC_TITLE_APPEARANCE); */
        beginbox(&cp, "Adjust the use of the cursor", IDC_BOX_APPEARANCE1);
        radioline(&cp, "Cursor appearance:", IDC_CURSORSTATIC, 3,
                  "B&lock", IDC_CURBLOCK,
@@ -1001,43 +1113,41 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        beginbox(&cp, "Adjust the window border", IDC_BOX_APPEARANCE5);
        checkbox(&cp, "&Sunken-edge border (slightly thicker)",
                 IDC_SUNKENEDGE);
+       staticedit(&cp, "Gap between text and window edge",
+                  IDC_WINBSTATIC, IDC_WINBEDIT, 20);
        endbox(&cp);
     }
 
     if (panel == translationpanelstart) {
-       /* The Translation panel. Accelerators used: [acgo] xbep t s */
+       /* The Translation panel. Accelerators used: [acgo] rxbepus */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling character set translation",
                 IDC_TITLE_TRANSLATION);
-       beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
+       beginbox(&cp, "Character set translation on received data",
                 IDC_BOX_TRANSLATION1);
+       combobox(&cp, "&Received data assumed to be in which character set:",
+                IDC_CODEPAGESTATIC, IDC_CODEPAGE);
+       endbox(&cp);
+        beginbox(&cp, "Enable character set translation on input data",
+                 IDC_BOX_TRANSLATION2);
+        checkbox(&cp, "Cap&s Lock acts as Cyrillic switch",
+                 IDC_CAPSLOCKCYR);
+        endbox(&cp);
+       beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
+                IDC_BOX_TRANSLATION3);
        radiobig(&cp,
                 "Handling of line drawing characters:", IDC_VTSTATIC,
                 "Font has &XWindows encoding", IDC_VTXWINDOWS,
                 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
                 "Use font in O&EM mode only", IDC_VTOEMONLY,
                 "&Poor man's line drawing (" "+" ", " "-" " and " "|" ")",
-                IDC_VTPOORMAN, NULL);
-       endbox(&cp);
-       beginbox(&cp, "Enable character set translation on received data",
-                IDC_BOX_TRANSLATION2);
-       radiobig(&cp,
-                "Character set &translation:", IDC_XLATSTATIC,
-                "None", IDC_NOXLAT,
-                "KOI8 / Win-1251", IDC_KOI8WIN1251,
-                "ISO-8859-2 / Win-1250", IDC_88592WIN1250,
-                "ISO-8859-2 / CP852", IDC_88592CP852, NULL);
-       endbox(&cp);
-       beginbox(&cp, "Enable character set translation on input data",
-                IDC_BOX_TRANSLATION3);
-       checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
-                IDC_CAPSLOCKCYR);
+                IDC_VTPOORMAN, "&Unicode mode", IDC_VTUNICODE, NULL);
        endbox(&cp);
     }
 
     if (panel == selectionpanelstart) {
-       /* The Selection panel. Accelerators used: [acgo] d wx hst */
+       /* The Selection panel. Accelerators used: [acgo] df wxp hst nr */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling copy and paste",
@@ -1047,6 +1157,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        checkbox(&cp,
                 "&Don't translate line drawing chars into +, - and |",
                 IDC_RAWCNP);
+       checkbox(&cp,
+                "Paste to clipboard in RT&F as well as plain text",
+                IDC_RTFPASTE);
        endbox(&cp);
        beginbox(&cp, "Control which mouse button does which thing",
                 IDC_BOX_SELECTION2);
@@ -1054,6 +1167,14 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
                 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
                 NULL);
+       checkbox(&cp,
+                "Shift overrides a&pplication's use of mouse",
+                IDC_MOUSEOVERRIDE);
+        radioline(&cp,
+                  "Default selection mode (Alt+drag does the other one):",
+                  IDC_SELTYPESTATIC, 2,
+                 "&Normal", IDC_SELTYPELEX,
+                 "&Rectangular block", IDC_SELTYPERECT, NULL);
        endbox(&cp);
        beginbox(&cp, "Control the select-one-word-at-a-time mode",
                 IDC_BOX_SELECTION3);
@@ -1158,7 +1279,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == sshpanelstart) {
-       /* The SSH panel. Accelerators used: [acgo] rmfkw pe123bds i */
+       /* The SSH panel. Accelerators used: [acgo] r pe12i s */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1169,46 +1290,101 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
                      NULL);
            endbox(&cp);
-           beginbox(&cp, "Authentication options", IDC_BOX_SSH2);
-           checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
-                    IDC_AUTHTIS);
-           checkbox(&cp, "Allow agent &forwarding", IDC_AGENTFWD);
-           editbutton(&cp, "Private &key file for authentication:",
-                      IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...",
-                      IDC_PKBUTTON);
-           endbox(&cp);
-           beginbox(&cp, "Protocol options", IDC_BOX_SSH3);
+           beginbox(&cp, "Protocol options", IDC_BOX_SSH2);
            checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
            checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
            radioline(&cp, "Preferred SSH protocol version:",
                      IDC_SSHPROTSTATIC, 2,
                      "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
-           radioline(&cp, "Preferred encryption algorithm:",
-                     IDC_CIPHERSTATIC, 4, "&3DES", IDC_CIPHER3DES,
-                     "&Blowfish", IDC_CIPHERBLOWF, "&DES", IDC_CIPHERDES,
-                     "AE&S", IDC_CIPHERAES, NULL);
            checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x",
                     IDC_BUGGYMAC);
            endbox(&cp);
+           beginbox(&cp, "Encryption options", IDC_BOX_SSH3);
+           prefslist(&cipherlist, &cp, "Encryption cipher &selection policy:",
+                     IDC_CIPHERSTATIC2, IDC_CIPHERLIST, IDC_CIPHERUP,
+                     IDC_CIPHERDN);
+           endbox(&cp);
+       }
+    }
+
+    if (panel == sshauthpanelstart) {
+       /* The SSH authentication panel. Accelerators used: [acgo] m fkw */
+       struct ctlpos cp;
+       ctlposinit(&cp, hwnd, 80, 3, 13);
+       if (dlgtype == 0) {
+           bartitle(&cp, "Options controlling SSH authentication",
+                    IDC_TITLE_SSHAUTH);
+           beginbox(&cp, "Authentication methods",
+                    IDC_BOX_SSHAUTH1);
+           checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
+                    IDC_AUTHTIS);
+           endbox(&cp);
+           beginbox(&cp, "Authentication parameters",
+                    IDC_BOX_SSHAUTH2);
+           checkbox(&cp, "Allow agent &forwarding", IDC_AGENTFWD);
+           editbutton(&cp, "Private &key file for authentication:",
+                      IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...",
+                      IDC_PKBUTTON);
+           endbox(&cp);
        }
     }
 
     if (panel == tunnelspanelstart) {
-       /* The Tunnels panel. Accelerators used: [acgo] ex */
+       /* The Tunnels panel. Accelerators used: [acgo] deilmrstx */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
            bartitle(&cp, "Options controlling SSH tunnelling",
                     IDC_TITLE_TUNNELS);
-           beginbox(&cp, "X11 forwarding options", IDC_BOX_TUNNELS);
+           beginbox(&cp, "X11 forwarding", IDC_BOX_TUNNELS1);
            checkbox(&cp, "&Enable X11 forwarding", IDC_X11_FORWARD);
            multiedit(&cp, "&X display location", IDC_X11_DISPSTATIC,
                      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);
+           staticbtn(&cp, "Forwarded ports:", IDC_PFWDSTATIC,
+                     "&Remove", IDC_PFWDREMOVE);
+           fwdsetter(&cp, IDC_PFWDLIST,
+                     "Add new forwarded port:", IDC_PFWDSTATIC2,
+                     "&Source port", IDC_SPORTSTATIC, IDC_SPORTEDIT,
+                     "Dest&ination", IDC_DPORTSTATIC, IDC_DPORTEDIT,
+                     "A&dd", IDC_PFWDADD);
+           bareradioline(&cp, 2,
+                         "&Local", IDC_PFWDLOCAL, "Re&mote", IDC_PFWDREMOTE, NULL);
+           endbox(&cp);
+
        }
     }
 }
 
+/* 
+ * Helper function to load the session selected in SESSLIST
+ * if any, as this is done in more than one place in
+ * GenericMainDlgProc(). 0 => failure.
+ */
+static int load_selected_session(HWND hwnd)
+{
+    int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
+                              LB_GETCURSEL, 0, 0);
+    int isdef;
+    if (n == LB_ERR) {
+       MessageBeep(0);
+       return 0;
+    }
+    isdef = !strcmp(sessions[n], "Default Settings");
+    load_settings(sessions[n], !isdef, &cfg);
+    init_dlg_ctrls(hwnd, TRUE);
+    if (!isdef)
+       SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
+    else
+       SetDlgItemText(hwnd, IDC_SESSEDIT, "");
+    /* Restore the selection, which will have been clobbered by
+     * SESSEDIT handling. */
+    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL, n, 0);
+    return 1;
+}
+
 /*
  * This function is the configuration box.
  */
@@ -1226,11 +1402,14 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
     char portname[32];
     struct servent *service;
     int i;
+    static UINT draglistmsg = WM_NULL;
 
     switch (msg) {
       case WM_INITDIALOG:
        readytogo = 0;
        SetWindowLong(hwnd, GWL_USERDATA, 0);
+       SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
+                   (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(IDI_CFGICON)));
        /*
         * Centre the window.
         */
@@ -1270,7 +1449,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
            r.left = 3;
            r.right = r.left + 75;
            r.top = 13;
-           r.bottom = r.top + 206;
+           r.bottom = r.top + 219;
            MapDialogRect(hwnd, &r);
            treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
                                      WS_CHILD | WS_VISIBLE |
@@ -1306,6 +1485,9 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
            treeview_insert(&tvfaff, 1, "Rlogin");
            if (backends[3].backend != NULL) {
                treeview_insert(&tvfaff, 1, "SSH");
+               /* XXX long name is ugly */
+               /* XXX make it closed by default? */
+               treeview_insert(&tvfaff, 2, "Auth");
                treeview_insert(&tvfaff, 2, "Tunnels");
            }
        }
@@ -1328,6 +1510,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        }
 
        SetWindowLong(hwnd, GWL_USERDATA, 1);
+       sesslist_has_focus = 0;
        return 0;
       case WM_LBUTTONUP:
        /*
@@ -1346,6 +1529,9 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
            TVITEM item;
            int j;
            char buffer[64];
+           SendMessage (hwnd, WM_SETREDRAW, FALSE, 0);
            item.hItem = i;
            item.pszText = buffer;
            item.cchTextMax = sizeof(buffer);
@@ -1380,6 +1566,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                create_controls(hwnd, dlgtype, rloginpanelstart);
            if (!strcmp(buffer, "SSH"))
                create_controls(hwnd, dlgtype, sshpanelstart);
+           if (!strcmp(buffer, "Auth"))
+               create_controls(hwnd, dlgtype, sshauthpanelstart);
            if (!strcmp(buffer, "Selection"))
                create_controls(hwnd, dlgtype, selectionpanelstart);
            if (!strcmp(buffer, "Colours"))
@@ -1387,7 +1575,10 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
            if (!strcmp(buffer, "Translation"))
                create_controls(hwnd, dlgtype, translationpanelstart);
 
-           init_dlg_ctrls(hwnd);
+           init_dlg_ctrls(hwnd, FALSE);
+           SendMessage (hwnd, WM_SETREDRAW, TRUE, 0);
+           InvalidateRect (hwnd, NULL, TRUE);
 
            SetFocus(((LPNMHDR) lParam)->hwndFrom);     /* ensure focus stays */
            return 0;
@@ -1400,6 +1591,16 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        if (GetWindowLong(hwnd, GWL_USERDATA) == 1)
            switch (LOWORD(wParam)) {
              case IDOK:
+               /* Behaviour of the "Open" button is different if the
+                * session list has focus, *unless* the user just
+                * double-clicked... */
+               if (sesslist_has_focus && !readytogo) {
+                   if (!load_selected_session(hwnd)) {
+                       MessageBeep(0);
+                       return 0;
+                   }
+               }
+               /* If at this point we have a valid session, go! */
                if (*cfg.host)
                    EndDialog(hwnd, 1);
                else
@@ -1479,6 +1680,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                                  &cfg);
                    get_sesslist(FALSE);
                    get_sesslist(TRUE);
+                   SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
+                                      FALSE, 0);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
                                       0, 0);
                    for (i = 0; i < nsessions; i++)
@@ -1487,32 +1690,28 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                                           (LPARAM) (sessions[i]));
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
                                       (WPARAM) - 1, 0);
+                   SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
+                                      TRUE, 0);
+                   InvalidateRect(GetDlgItem(hwnd, IDC_SESSLIST), NULL,
+                                  TRUE);
                }
                break;
              case IDC_SESSLIST:
              case IDC_SESSLOAD:
+               if (LOWORD(wParam) == IDC_SESSLIST) {
+                   if (HIWORD(wParam) == LBN_SETFOCUS)
+                       sesslist_has_focus = 1;
+                   else if (HIWORD(wParam) == LBN_KILLFOCUS)
+                       sesslist_has_focus = 0;
+               }
                if (LOWORD(wParam) == IDC_SESSLOAD &&
                    HIWORD(wParam) != BN_CLICKED &&
                    HIWORD(wParam) != BN_DOUBLECLICKED) break;
                if (LOWORD(wParam) == IDC_SESSLIST &&
                    HIWORD(wParam) != LBN_DBLCLK) break;
-               {
-                   int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
-                                              LB_GETCURSEL, 0, 0);
-                   int isdef;
-                   if (n == LB_ERR) {
-                       MessageBeep(0);
-                       break;
-                   }
-                   isdef = !strcmp(sessions[n], "Default Settings");
-                   load_settings(sessions[n], !isdef, &cfg);
-                   init_dlg_ctrls(hwnd);
-                   if (!isdef)
-                       SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
-                   else
-                       SetDlgItemText(hwnd, IDC_SESSEDIT, "");
-               }
-               if (LOWORD(wParam) == IDC_SESSLIST) {
+               /* Load the session selected in SESSLIST. */
+               if (load_selected_session(hwnd) &&
+                   LOWORD(wParam) == IDC_SESSLIST) {
                    /*
                     * A double-click on a saved session should
                     * actually start the session, not just load it.
@@ -1537,6 +1736,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    del_settings(sessions[n]);
                    get_sesslist(FALSE);
                    get_sesslist(TRUE);
+                   SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
+                                      FALSE, 0);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
                                       0, 0);
                    for (i = 0; i < nsessions; i++)
@@ -1545,6 +1746,10 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                                           (LPARAM) (sessions[i]));
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
                                       (WPARAM) - 1, 0);
+                   SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
+                                      TRUE, 0);
+                   InvalidateRect(GetDlgItem(hwnd, IDC_SESSLIST), NULL,
+                                  TRUE);
                }
              case IDC_PINGEDIT:
                if (HIWORD(wParam) == EN_CHANGE)
@@ -1683,6 +1888,12 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.alwaysontop =
                        IsDlgButtonChecked(hwnd, IDC_ALWAYSONTOP);
                break;
+             case IDC_FULLSCREENONALTENTER:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.fullscreenonaltenter =
+                       IsDlgButtonChecked(hwnd, IDC_FULLSCREENONALTENTER);
+               break;
              case IDC_SCROLLKEY:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -1794,6 +2005,19 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.beep = BELL_VISUAL;
                }
                break;
+             case IDC_B_IND_DISABLED:
+             case IDC_B_IND_FLASH:
+             case IDC_B_IND_STEADY:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   if (LOWORD(wParam) == IDC_B_IND_DISABLED)
+                       cfg.beep_ind = B_IND_DISABLED;
+                   if (LOWORD(wParam) == IDC_B_IND_FLASH)
+                       cfg.beep_ind = B_IND_FLASH;
+                   if (LOWORD(wParam) == IDC_B_IND_STEADY)
+                       cfg.beep_ind = B_IND_STEADY;
+               }
+               break;
              case IDC_BELL_WAVEBROWSE:
                memset(&of, 0, sizeof(of));
 #ifdef OPENFILENAME_SIZE_VERSION_400
@@ -1873,6 +2097,13 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.sunken_edge =
                        IsDlgButtonChecked(hwnd, IDC_SUNKENEDGE);
                break;
+             case IDC_WINBEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   MyGetDlgItemInt(hwnd, IDC_WINBEDIT,
+                                   &cfg.window_border);
+               if (cfg.window_border > 32)
+                   cfg.window_border = 32;
+               break;
              case IDC_CURBLOCK:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -1900,11 +2131,24 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.scrollbar =
                        IsDlgButtonChecked(hwnd, IDC_SCROLLBAR);
                break;
-             case IDC_LOCKSIZE:
+             case IDC_SCROLLBARFULLSCREEN:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
-                       cfg.locksize =
-                       IsDlgButtonChecked(hwnd, IDC_LOCKSIZE);
+                   cfg.scrollbar_in_fullscreen =
+                   IsDlgButtonChecked(hwnd, IDC_SCROLLBARFULLSCREEN);
+               break;
+             case IDC_RESIZETERM:
+             case IDC_RESIZEFONT:
+             case IDC_RESIZENONE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   cfg.resize_action =
+                       IsDlgButtonChecked(hwnd,
+                                          IDC_RESIZETERM) ? RESIZE_TERM :
+                       IsDlgButtonChecked(hwnd,
+                                          IDC_RESIZEFONT) ? RESIZE_FONT :
+                       RESIZE_DISABLED;
+               }
                break;
              case IDC_WINEDIT:
                if (HIWORD(wParam) == EN_CHANGE)
@@ -2114,21 +2358,12 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.agentfwd =
                        IsDlgButtonChecked(hwnd, IDC_AGENTFWD);
                break;
-             case IDC_CIPHER3DES:
-             case IDC_CIPHERBLOWF:
-             case IDC_CIPHERDES:
-             case IDC_CIPHERAES:
-               if (HIWORD(wParam) == BN_CLICKED ||
-                   HIWORD(wParam) == BN_DOUBLECLICKED) {
-                   if (IsDlgButtonChecked(hwnd, IDC_CIPHER3DES))
-                       cfg.cipher = CIPHER_3DES;
-                   else if (IsDlgButtonChecked(hwnd, IDC_CIPHERBLOWF))
-                       cfg.cipher = CIPHER_BLOWFISH;
-                   else if (IsDlgButtonChecked(hwnd, IDC_CIPHERDES))
-                       cfg.cipher = CIPHER_DES;
-                   else if (IsDlgButtonChecked(hwnd, IDC_CIPHERAES))
-                       cfg.cipher = CIPHER_AES;
-               }
+             case IDC_CIPHERLIST:
+             case IDC_CIPHERUP:
+             case IDC_CIPHERDN:
+               handle_prefslist(&cipherlist,
+                                cfg.ssh_cipherlist, CIPHER_MAX,
+                                0, hwnd, wParam, lParam);
                break;
              case IDC_SSHPROT1:
              case IDC_SSHPROT2:
@@ -2172,7 +2407,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                of.nMaxFile = sizeof(filename);
                of.lpstrFileTitle = NULL;
                of.lpstrInitialDir = NULL;
-               of.lpstrTitle = "Select Public Key File";
+               of.lpstrTitle = "Select Private Key File";
                of.Flags = 0;
                if (GetOpenFileName(&of)) {
                    strcpy(cfg.keyfile, filename);
@@ -2181,10 +2416,21 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                break;
              case IDC_RAWCNP:
                cfg.rawcnp = IsDlgButtonChecked(hwnd, IDC_RAWCNP);
+               break;
+             case IDC_RTFPASTE:
+               cfg.rtf_paste = IsDlgButtonChecked(hwnd, IDC_RTFPASTE);
+               break;
              case IDC_MBWINDOWS:
              case IDC_MBXTERM:
                cfg.mouse_is_xterm = IsDlgButtonChecked(hwnd, IDC_MBXTERM);
                break;
+             case IDC_SELTYPELEX:
+             case IDC_SELTYPERECT:
+               cfg.rect_select = IsDlgButtonChecked(hwnd, IDC_SELTYPERECT);
+               break;
+             case IDC_MOUSEOVERRIDE:
+               cfg.mouse_override = IsDlgButtonChecked(hwnd, IDC_MOUSEOVERRIDE);
+               break;
              case IDC_CCSET:
                {
                    BOOL ok;
@@ -2194,7 +2440,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    if (!ok)
                        MessageBeep(0);
                    else {
-                       for (i = 0; i < 256; i++)
+                       for (i = 0; i < 128; i++)
                            if (SendDlgItemMessage
                                (hwnd, IDC_CCLIST, LB_GETSEL, i, 0)) {
                                char str[100];
@@ -2217,6 +2463,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    int n, i;
                    cfg.bold_colour =
                        IsDlgButtonChecked(hwnd, IDC_BOLDCOLOUR);
+                   SendDlgItemMessage(hwnd, IDC_COLOURLIST, WM_SETREDRAW,
+                                      FALSE, 0);
                    n =
                        SendDlgItemMessage(hwnd, IDC_COLOURLIST,
                                           LB_GETCOUNT, 0, 0);
@@ -2230,6 +2478,10 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                                                   LB_ADDSTRING, 0,
                                                   (LPARAM) colours[i]);
                    }
+                   SendDlgItemMessage(hwnd, IDC_COLOURLIST, WM_SETREDRAW,
+                                      TRUE, 0);
+                   InvalidateRect(GetDlgItem(hwnd, IDC_COLOURLIST), NULL,
+                                  TRUE);
                }
                break;
              case IDC_PALETTE:
@@ -2241,9 +2493,10 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
              case IDC_COLOURLIST:
                if (HIWORD(wParam) == LBN_DBLCLK ||
                    HIWORD(wParam) == LBN_SELCHANGE) {
-                   int i = SendDlgItemMessage(hwnd, IDC_COLOURLIST,
-                                              LB_GETCURSEL,
-                                              0, 0);
+                   int i =
+                       SendDlgItemMessage(hwnd, IDC_COLOURLIST,
+                                          LB_GETCURSEL,
+                                          0, 0);
                    if (!cfg.bold_colour)
                        i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
                    SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
@@ -2259,9 +2512,10 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    HIWORD(wParam) == BN_DOUBLECLICKED) {
                    static CHOOSECOLOR cc;
                    static DWORD custom[16] = { 0 };    /* zero initialisers */
-                   int i = SendDlgItemMessage(hwnd, IDC_COLOURLIST,
-                                              LB_GETCURSEL,
-                                              0, 0);
+                   int i =
+                       SendDlgItemMessage(hwnd, IDC_COLOURLIST,
+                                          LB_GETCURSEL,
+                                          0, 0);
                    if (!cfg.bold_colour)
                        i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
                    cc.lStructSize = sizeof(cc);
@@ -2288,34 +2542,41 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    }
                }
                break;
-             case IDC_NOXLAT:
-             case IDC_KOI8WIN1251:
-             case IDC_88592WIN1250:
-             case IDC_88592CP852:
-               cfg.xlat_enablekoiwin =
-                   IsDlgButtonChecked(hwnd, IDC_KOI8WIN1251);
-               cfg.xlat_88592w1250 =
-                   IsDlgButtonChecked(hwnd, IDC_88592WIN1250);
-               cfg.xlat_88592cp852 =
-                   IsDlgButtonChecked(hwnd, IDC_88592CP852);
+             case IDC_CODEPAGE:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_CODEPAGE,
+                                                  CB_GETCURSEL, 0, 0);
+                   SendDlgItemMessage(hwnd, IDC_CODEPAGE, CB_GETLBTEXT,
+                                      index, (LPARAM)cfg.line_codepage);
+               } else if (HIWORD(wParam) == CBN_EDITCHANGE) {
+                   GetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage,
+                                  sizeof(cfg.line_codepage) - 1);
+               } else if (HIWORD(wParam) == CBN_KILLFOCUS) {
+                   strcpy(cfg.line_codepage,
+                          cp_name(decode_codepage(cfg.line_codepage)));
+                   SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
+               }
                break;
              case IDC_CAPSLOCKCYR:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED) {
                    cfg.xlat_capslockcyr =
-                       IsDlgButtonChecked(hwnd, IDC_CAPSLOCKCYR);
+                       IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
                }
                break;
              case IDC_VTXWINDOWS:
              case IDC_VTOEMANSI:
              case IDC_VTOEMONLY:
              case IDC_VTPOORMAN:
+             case IDC_VTUNICODE:
                cfg.vtmode =
                    (IsDlgButtonChecked(hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS
                     : IsDlgButtonChecked(hwnd,
                                          IDC_VTOEMANSI) ? VT_OEMANSI :
                     IsDlgButtonChecked(hwnd,
                                        IDC_VTOEMONLY) ? VT_OEMONLY :
+                    IsDlgButtonChecked(hwnd,
+                                       IDC_VTUNICODE) ? VT_UNICODE :
                     VT_POORMAN);
                break;
              case IDC_X11_FORWARD:
@@ -2324,11 +2585,101 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        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);
+               break;
              case IDC_X11_DISPLAY:
                if (HIWORD(wParam) == EN_CHANGE)
                    GetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display,
                                   sizeof(cfg.x11_display) - 1);
                break;
+             case IDC_PFWDADD:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   char str[sizeof(cfg.portfwd)];
+                   char *p;
+                   if (IsDlgButtonChecked(hwnd, IDC_PFWDLOCAL))
+                       str[0] = 'L';
+                   else
+                       str[0] = 'R';
+                   GetDlgItemText(hwnd, IDC_SPORTEDIT, str+1,
+                                  sizeof(str) - 2);
+                   if (!str[1]) {
+                       MessageBox(hwnd,
+                                  "You need to specify a source port number",
+                                  "PuTTY Error", MB_OK | MB_ICONERROR);
+                       break;
+                   }
+                   p = str + strlen(str);
+                   *p++ = '\t';
+                   GetDlgItemText(hwnd, IDC_DPORTEDIT, p,
+                                  sizeof(str) - 1 - (p - str));
+                   if (!*p || !strchr(p, ':')) {
+                       MessageBox(hwnd,
+                                  "You need to specify a destination address\n"
+                                  "in the form \"host.name:port\"",
+                                  "PuTTY Error", MB_OK | MB_ICONERROR);
+                       break;
+                   }
+                   p = cfg.portfwd;
+                   while (*p) {
+                       while (*p)
+                           p++;
+                       p++;
+                   }
+                   if ((p - cfg.portfwd) + strlen(str) + 2 <
+                       sizeof(cfg.portfwd)) {
+                       strcpy(p, str);
+                       p[strlen(str) + 1] = '\0';
+                       SendDlgItemMessage(hwnd, IDC_PFWDLIST, LB_ADDSTRING,
+                                          0, (LPARAM) str);
+                       SetDlgItemText(hwnd, IDC_SPORTEDIT, "");
+                       SetDlgItemText(hwnd, IDC_DPORTEDIT, "");
+                   } else {
+                       MessageBox(hwnd, "Too many forwardings",
+                                  "PuTTY Error", MB_OK | MB_ICONERROR);
+                   }
+               }
+               break;
+             case IDC_PFWDREMOVE:
+               if (HIWORD(wParam) != BN_CLICKED &&
+                   HIWORD(wParam) != BN_DOUBLECLICKED) break;
+               i = SendDlgItemMessage(hwnd, IDC_PFWDLIST,
+                                      LB_GETCURSEL, 0, 0);
+               if (i == LB_ERR)
+                   MessageBeep(0);
+               else {
+                   char *p, *q;
+
+                   SendDlgItemMessage(hwnd, IDC_PFWDLIST, LB_DELETESTRING,
+                                      i, 0);
+                   p = cfg.portfwd;
+                   while (i > 0) {
+                       if (!*p)
+                           goto disaster2;
+                       while (*p)
+                           p++;
+                       p++;
+                       i--;
+                   }
+                   q = p;
+                   if (!*p)
+                       goto disaster2;
+                   while (*p)
+                       p++;
+                   p++;
+                   while (*p) {
+                       while (*p)
+                           *q++ = *p++;
+                       *q++ = *p++;
+                   }
+                   *q = '\0';
+                 disaster2:;
+               }
+               break;
            }
        return 0;
       case WM_CLOSE:
@@ -2340,6 +2691,26 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        if (wParam == SIZE_MAXIMIZED)
            force_normal(hwnd);
        return 0;
+
+      default:
+       /*
+        * Handle application-defined messages eg. DragListBox
+        */
+       /* First find out what the number is (once). */
+       if (draglistmsg == WM_NULL)
+           draglistmsg = RegisterWindowMessage (DRAGLISTMSGSTRING);
+
+       if (msg == draglistmsg) {
+           /* Only process once dialog is fully formed. */
+           if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
+             case IDC_CIPHERLIST:
+               return handle_prefslist(&cipherlist,
+                                       cfg.ssh_cipherlist, CIPHER_MAX,
+                                       1, hwnd, wParam, lParam);
+           }
+       }
+       return 0;
+
     }
     return 0;
 }
@@ -2351,8 +2722,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
     }
     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
        EnableWindow(hwnd, 0);
-       DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
-                 GetParent(hwnd), AboutProc);
+       DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
        EnableWindow(hwnd, 1);
        SetActiveWindow(hwnd);
     }
@@ -2377,6 +2747,7 @@ void defuse_showwindow(void)
        hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
                            NULL, NullDlgProc);
        ShowWindow(hwnd, SW_HIDE);
+       SetActiveWindow(hwnd);
        DestroyWindow(hwnd);
     }
 }
@@ -2463,7 +2834,9 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        "%s\n"
        "If you trust this host, hit Yes to add the key to\n"
        "PuTTY's cache and carry on connecting.\n"
-       "If you do not trust this host, hit No to abandon the\n"
+       "If you want to carry on connecting just once, without\n"
+       "adding the key to the cache, hit No.\n"
+       "If you do not trust this host, hit Cancel to abandon the\n"
        "connection.\n";
 
     static const char wrongmsg[] =
@@ -2485,9 +2858,8 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
 
     static const char mbtitle[] = "PuTTY Security Alert";
 
-
     char message[160 +
-                /* sensible fingerprint max size */
+       /* sensible fingerprint max size */
        (sizeof(absentmsg) > sizeof(wrongmsg) ?
         sizeof(absentmsg) : sizeof(wrongmsg))];
 
@@ -2512,14 +2884,45 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        int mbret;
        sprintf(message, absentmsg, fingerprint);
        mbret = MessageBox(NULL, message, mbtitle,
-                          MB_ICONWARNING | MB_YESNO);
-       if (mbret == IDNO)
+                          MB_ICONWARNING | MB_YESNOCANCEL);
+       if (mbret == IDYES)
+           store_host_key(host, port, keytype, keystr);
+       if (mbret == IDCANCEL)
            exit(0);
-       store_host_key(host, port, keytype, keystr);
     }
 }
 
 /*
+ * Ask whether the selected cipher is acceptable (since it was
+ * below the configured 'warn' threshold).
+ * cs: 0 = both ways, 1 = client->server, 2 = server->client
+ */
+void askcipher(char *ciphername, int cs)
+{
+    static const char mbtitle[] = "PuTTY Security Alert";
+    static const char msg[] =
+       "The first %.35scipher supported by the server\n"
+       "is %.64s, which is below the configured\n"
+       "warning threshold.\n"
+       "Do you want to continue with this connection?\n";
+    /* guessed cipher name + type max length */
+    char message[100 + sizeof(msg)];
+    int mbret;
+
+    sprintf(message, msg,
+           (cs == 0) ? "" :
+           (cs == 1) ? "client-to-server " :
+                       "server-to-client ",
+           ciphername);
+    mbret = MessageBox(NULL, message, mbtitle,
+                      MB_ICONWARNING | MB_YESNO);
+    if (mbret == IDYES)
+       return;
+    else
+       exit(0);
+}
+
+/*
  * Ask whether to wipe a session log file before writing to it.
  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
  */