Yet another possible segfault path in the backends fixed. I don't
[u/mdw/putty] / windlg.c
index eb01fc2..793bb08 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -16,6 +16,7 @@ static char **events = NULL;
 static int nevents = 0, negsize = 0;
 
 static int readytogo;
+static int sesslist_has_focus;
 
 void force_normal(HWND hwnd)
 {
@@ -128,7 +129,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);
@@ -291,6 +292,7 @@ enum { IDCX_ABOUT =
     IDC_CURAPPLIC,
     IDC_COMPOSEKEY,
     IDC_CTRLALTKEYS,
+    IDC_TELNETKEY,
     keyboardpanelend,
 
     terminalpanelstart,
@@ -326,6 +328,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,
@@ -485,18 +491,14 @@ enum { IDCX_ABOUT =
     IDC_TITLE_TRANSLATION,
     IDC_BOX_TRANSLATION1,
     IDC_BOX_TRANSLATION2,
-    IDC_BOX_TRANSLATION3,
-    IDC_XLATSTATIC,
-    IDC_NOXLAT,
-    IDC_KOI8WIN1251,
-    IDC_88592WIN1250,
-    IDC_88592CP852,
-    IDC_CAPSLOCKCYR,
+    IDC_CODEPAGESTATIC,
+    IDC_CODEPAGE,
     IDC_VTSTATIC,
     IDC_VTXWINDOWS,
     IDC_VTOEMANSI,
     IDC_VTOEMONLY,
     IDC_VTPOORMAN,
+    IDC_VTUNICODE,
     translationpanelend,
 
     tunnelspanelstart,
@@ -541,14 +543,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;)
@@ -588,6 +592,7 @@ static void init_dlg_ctrls(HWND hwnd)
     CheckDlgButton(hwnd, IDC_ALTONLY, cfg.alt_only);
     CheckDlgButton(hwnd, IDC_COMPOSEKEY, cfg.compose_key);
     CheckDlgButton(hwnd, IDC_CTRLALTKEYS, cfg.ctrlaltkeys);
+    CheckDlgButton(hwnd, IDC_TELNETKEY, cfg.telnet_keyboard);
     CheckRadioButton(hwnd, IDC_ECHOBACKEND, IDC_ECHONO,
                     cfg.localecho == LD_BACKEND ? IDC_ECHOBACKEND :
                     cfg.localecho == LD_YES ? IDC_ECHOYES : IDC_ECHONO);
@@ -613,6 +618,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);
@@ -689,7 +699,7 @@ static void init_dlg_ctrls(HWND hwnd)
        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]);
@@ -715,15 +725,12 @@ 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,
+    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);
@@ -779,7 +786,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      "&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);
@@ -863,7 +870,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",
@@ -878,6 +885,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);
@@ -1016,21 +1027,12 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                 "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);
+                IDC_VTPOORMAN, "&Unicode mode", IDC_VTUNICODE, 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);
+       multiedit(&cp, "Line codepage:", IDC_CODEPAGESTATIC,
+                 IDC_CODEPAGE, 100, NULL);
        endbox(&cp);
     }
 
@@ -1098,6 +1100,11 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC,
                       IDC_LOGEDIT, 50);
            endbox(&cp);
+       } else {
+           beginbox(&cp, "Adjust telnet session.", IDC_BOX_CONNECTION1);
+           checkbox(&cp, "Keyboard sends telnet Backspace and Interrupt",
+                    IDC_TELNETKEY);
+           endbox(&cp);
        }
        beginbox(&cp, "Sending of null packets to keep session active",
                 IDC_BOX_CONNECTION2);
@@ -1107,7 +1114,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == telnetpanelstart) {
-       /* The Telnet panel. Accelerators used: [acgo] svldr bft */
+       /* The Telnet panel. Accelerators used: [acgo] svldr bftk */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1128,6 +1135,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            radioline(&cp, "&Telnet negotiation mode:", IDC_ACTSTATIC, 2,
                      "Passive", IDC_TPASSIVE, "Active",
                      IDC_TACTIVE, NULL);
+           checkbox(&cp, "&Keyboard sends telnet Backspace and Interrupt",
+                    IDC_TELNETKEY);
            endbox(&cp);
        }
     }
@@ -1200,6 +1209,33 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 }
 
+/* 
+ * 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.
  */
@@ -1222,6 +1258,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT 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.
         */
@@ -1319,6 +1357,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        }
 
        SetWindowLong(hwnd, GWL_USERDATA, 1);
+       sesslist_has_focus = 0;
        return 0;
       case WM_LBUTTONUP:
        /*
@@ -1378,7 +1417,7 @@ 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);
 
            SetFocus(((LPNMHDR) lParam)->hwndFrom);     /* ensure focus stays */
            return 0;
@@ -1391,6 +1430,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
@@ -1470,6 +1519,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++)
@@ -1478,32 +1529,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.
@@ -1528,6 +1575,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++)
@@ -1536,6 +1585,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)
@@ -1698,6 +1751,12 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.ctrlaltkeys =
                        IsDlgButtonChecked(hwnd, IDC_CTRLALTKEYS);
                break;
+             case IDC_TELNETKEY:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.telnet_keyboard =
+                       IsDlgButtonChecked(hwnd, IDC_TELNETKEY);
+               break;
              case IDC_WRAPMODE:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -1779,6 +1838,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
@@ -2179,7 +2251,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];
@@ -2202,6 +2274,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);
@@ -2215,6 +2289,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:
@@ -2226,9 +2304,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],
@@ -2244,9 +2323,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);
@@ -2273,34 +2353,44 @@ 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);
-               break;
-             case IDC_CAPSLOCKCYR:
-               if (HIWORD(wParam) == BN_CLICKED ||
-                   HIWORD(wParam) == BN_DOUBLECLICKED) {
-                   cfg.xlat_capslockcyr =
-                       IsDlgButtonChecked(hwnd, IDC_CAPSLOCKCYR);
+             case IDC_CODEPAGE:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage,
+                                  sizeof(cfg.line_codepage) - 1);
+               if (HIWORD(wParam) == EN_KILLFOCUS) {
+                   int cp = decode_codepage(cfg.line_codepage);
+                   char buf[256];
+                   if (cp < -1) {
+                       if (cp == -2)
+                           sprintf(buf,
+                                   "Unable to identify character set '%s', "
+                                   "translation disabled.",
+                                   cfg.line_codepage);
+                       if (cp == -3)
+                           sprintf(buf,
+                                   "Character set '%s' is a DBCS, "
+                                   "translation is not available.",
+                                   cfg.line_codepage);
+                       MessageBox(hwnd, buf, "PuTTY Error",
+                                  MB_ICONERROR | MB_OK);
+                   }
+                   strcpy(cfg.line_codepage, cp_name(cp));
+                   SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
                }
                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:
@@ -2336,8 +2426,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);
     }
@@ -2362,6 +2451,7 @@ void defuse_showwindow(void)
        hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
                            NULL, NullDlgProc);
        ShowWindow(hwnd, SW_HIDE);
+       SetActiveWindow(hwnd);
        DestroyWindow(hwnd);
     }
 }
@@ -2448,7 +2538,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[] =
@@ -2470,9 +2562,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))];
 
@@ -2497,10 +2588,11 @@ 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);
     }
 }