Experimental Rlogin support, thanks to Delian Delchev. Local flow
[u/mdw/putty] / windlg.c
index a912df8..62b49d0 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -17,7 +17,7 @@ static HWND logbox = NULL, abtbox = NULL;
 
 static int readytogo;
 
-static void force_normal(HWND hwnd)
+void force_normal(HWND hwnd)
 {
     static int recurse = 0;
 
@@ -27,7 +27,7 @@ static void force_normal(HWND hwnd)
     recurse = 1;
 
     wp.length = sizeof(wp);
-    if (GetWindowPlacement(hwnd, &wp))
+    if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED)
     {
        wp.showCmd = SW_SHOWNORMAL;
        SetWindowPlacement(hwnd, &wp);
@@ -66,7 +66,7 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg,
                 int *selitems;
                 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
                                               LB_GETSELCOUNT, 0, 0);
-                selitems = malloc(selcount * sizeof(int));
+                selitems = smalloc(selcount * sizeof(int));
                 if (selitems) {
                     int count = SendDlgItemMessage(hwnd, IDN_LIST,
                                                    LB_GETSELITEMS,
@@ -85,7 +85,7 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg,
                     for (i = 0; i < count; i++)
                         size += strlen(events[selitems[i]]) + sizeof(sel_nl);
 
-                    clipdata = malloc(size);
+                    clipdata = smalloc(size);
                     if (clipdata) {
                         char *p = clipdata;
                         for (i = 0; i < count; i++) {
@@ -97,9 +97,9 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg,
                             p += sizeof(sel_nl);
                         }
                         write_clip(clipdata, size, TRUE);
-                        free(clipdata);
+                        sfree(clipdata);
                     }
-                    free(selitems);
+                    sfree(selitems);
 
                     for (i = 0; i < nevents; i++)
                         SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
@@ -189,6 +189,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
     IDC_PROTSTATIC,
     IDC_PROTRAW,
     IDC_PROTTELNET,
+    IDC_PROTRLOGIN,
     IDC_PROTSSH,
     IDC_SESSSTATIC,
     IDC_SESSEDIT,
@@ -230,6 +231,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
     terminalpanelstart,
     IDC_TITLE_TERMINAL,
     IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
+    IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2,
     IDC_WRAPMODE,
     IDC_DECOM,
     IDC_LFHASCR,
@@ -237,6 +239,13 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
     IDC_BCE,
     IDC_BLINKTEXT,
     IDC_LDISCTERM,
+    IDC_LSTATSTATIC,
+    IDC_LSTATOFF,
+    IDC_LSTATASCII,
+    IDC_LSTATRAW,
+    IDC_LGFSTATIC,
+    IDC_LGFEDIT,
+    IDC_LGFBUTTON,
     terminalpanelend,
 
     windowpanelstart,
@@ -266,6 +275,10 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
     IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1,
     IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2,
     IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3,
+    IDC_CURSORSTATIC,
+    IDC_CURBLOCK,
+    IDC_CURUNDER,
+    IDC_CURVERT,
     IDC_BLINKCUR,
     IDC_FONTSTATIC,
     IDC_CHOOSEFONT,
@@ -305,6 +318,16 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
     IDC_EMRFC,
     telnetpanelend,
 
+    rloginpanelstart,
+    IDC_TITLE_RLOGIN,
+    IDC_BOX_RLOGIN1, IDC_BOXT_RLOGIN1,
+    IDC_BOX_RLOGIN2, IDC_BOXT_RLOGIN2,
+    IDC_R_TSSTATIC,
+    IDC_R_TSEDIT,
+    IDC_RLLUSERSTATIC,
+    IDC_RLLUSEREDIT,
+    rloginpanelend,
+
     sshpanelstart,
     IDC_TITLE_SSH,
     IDC_BOX_SSH1, IDC_BOXT_SSH1,
@@ -326,6 +349,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
     IDC_AGENTFWD,
     IDC_CMDSTATIC,
     IDC_CMDEDIT,
+    IDC_COMPRESS,
     sshpanelend,
 
     selectionpanelstart,
@@ -420,7 +444,8 @@ static void init_dlg_ctrls(HWND hwnd) {
     SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
     CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
                      cfg.protocol==PROT_SSH ? IDC_PROTSSH :
-                     cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
+                     cfg.protocol==PROT_TELNET ? IDC_PROTTELNET :
+                      cfg.protocol==PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW );
     SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
 
     CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
@@ -463,6 +488,9 @@ static void init_dlg_ctrls(HWND hwnd) {
 
     SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
     CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
+    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);
@@ -471,7 +499,14 @@ static void init_dlg_ctrls(HWND hwnd) {
 
     SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
     SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
+    SetDlgItemText (hwnd, IDC_R_TSEDIT, cfg.termspeed);
+    SetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername);
     SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
+    SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
+    CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
+                    cfg.logtype == 0 ? IDC_LSTATOFF :
+                    cfg.logtype == 1 ? IDC_LSTATASCII :
+                    IDC_LSTATRAW);
     {
        char *p = cfg.environmt;
        while (*p) {
@@ -486,6 +521,7 @@ static void init_dlg_ctrls(HWND hwnd) {
     SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
     SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
     CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
+    CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
     CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
     CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
     CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
@@ -517,7 +553,11 @@ static void init_dlg_ctrls(HWND hwnd) {
     CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
     CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
     {
-       int i;
+       int i, n;
+       n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
+       for (i=n; i-- >0 ;)
+           SendDlgItemMessage (hwnd, IDC_COLOURLIST,
+                                   LB_DELETESTRING, i, 0);
        for (i=0; i<22; i++)
            if (cfg.bold_colour || permcolour[i])
                SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
@@ -592,6 +632,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
     CHOOSEFONT cf;
     LOGFONT lf;
     char fontstatic[256];
+    char portname[32];
+    struct servent * service;
     int i;
 
     switch (msg) {
@@ -631,7 +673,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
            SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
 
             r.left = 3; r.right = r.left + 75;
-            r.top = 13; r.bottom = r.top + 196;
+            r.top = 13; r.bottom = r.top + 206;
             MapDialogRect(hwnd, &r);
             treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
                                       WS_CHILD | WS_VISIBLE |
@@ -665,13 +707,15 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                          "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
                if (backends[2].backend == NULL) {
                    /* this is PuTTYtel, so only two protocols available */
-                   radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
+                   radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
                              "&Raw", IDC_PROTRAW,
-                             "&Telnet", IDC_PROTTELNET, NULL);
+                             "&Telnet", IDC_PROTTELNET,
+                             "R&login", IDC_PROTRLOGIN, NULL);
                } else {
-                   radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
+                   radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
                              "&Raw", IDC_PROTRAW,
                              "&Telnet", IDC_PROTTELNET,
+                             "R&login", IDC_PROTRLOGIN,
 #ifdef FWHACK
                              "SS&H/hack",
 #else
@@ -696,7 +740,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
             hsession = treeview_insert(&tvfaff, 0, "Session");
        }
 
-        /* The Terminal panel. Accelerators used: [acgo] &dlbenu */
+        /* The Terminal panel. Accelerators used: [acgo] &dflbenuw */
        {
            struct ctlpos cp;
            ctlposinit(&cp, hwnd, 80, 3, 13);
@@ -713,6 +757,18 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
             checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
             endbox(&cp);
 
+           beginbox(&cp, "Control session logging",
+                    IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
+           radiobig(&cp,
+                    "Session logging:", IDC_LSTATSTATIC,
+                    "Logging turned &off completely", IDC_LSTATOFF,
+                    "Log printable output only", IDC_LSTATASCII,
+                    "Log all session output", IDC_LSTATRAW, NULL);
+           editbutton(&cp, "Log &file name:",
+                      IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
+                      IDC_LGFBUTTON);
+           endbox(&cp);
+
             treeview_insert(&tvfaff, 0, "Terminal");
        }
 
@@ -795,7 +851,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
             treeview_insert(&tvfaff, 0, "Window");
        }
 
-        /* The Appearance panel. Accelerators used: [acgo] rmkhti */
+        /* The Appearance panel. Accelerators used: [acgo] rmkhtibluv */
        {
            struct ctlpos cp;
            ctlposinit(&cp, hwnd, 80, 3, 13);
@@ -803,6 +859,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                      IDC_TITLE_APPEARANCE);
             beginbox(&cp, "Adjust the use of the cursor",
                      IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1);
+           radioline(&cp, "Cursor appearance:", IDC_CURSORSTATIC, 3,
+                     "B&lock", IDC_CURBLOCK,
+                     "&Underline", IDC_CURUNDER,
+                     "&Vertical line", IDC_CURVERT,
+                     NULL);
            checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
             endbox(&cp);
             beginbox(&cp, "Set the font used in the terminal window",
@@ -811,10 +872,9 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
             endbox(&cp);
             beginbox(&cp, "Adjust the use of the window title",
                      IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3);
-           if (dlgtype == 0)
-               multiedit(&cp,
-                         "Initial window &title:", IDC_WINTITLE,
-                         IDC_WINEDIT, 100, NULL);
+            multiedit(&cp,
+                      "Window &title:", IDC_WINTITLE,
+                      IDC_WINEDIT, 100, NULL);
            checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
             endbox(&cp);
 
@@ -916,7 +976,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
             }
             beginbox(&cp, "Sending of null packets to keep session active",
                      IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
-            staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
+            staticedit(&cp, "Seconds between &keepalives (0 to turn off)",
                        IDC_PINGSTATIC, IDC_PINGEDIT, 25);
             endbox(&cp);
 
@@ -949,6 +1009,23 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
            }
        }
 
+
+       /* The Rlogin Panel */
+       {
+           struct ctlpos cp;
+           ctlposinit(&cp, hwnd, 80, 3, 13);
+           if (dlgtype == 0) {
+                bartitle(&cp, "Options controlling Rlogin connections", IDC_TITLE_RLOGIN);
+                beginbox(&cp, "Data to send to the server",
+                         IDC_BOX_RLOGIN1, IDC_BOXT_RLOGIN1);
+               staticedit(&cp, "Terminal-&speed string", IDC_R_TSSTATIC, IDC_R_TSEDIT, 50);
+               staticedit(&cp, "&Local username:", IDC_RLLUSERSTATIC, IDC_RLLUSEREDIT, 50);
+                endbox(&cp);
+
+                treeview_insert(&tvfaff, 1, "Rlogin");
+           }
+       }
+
        /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
         if (backends[2].backend != NULL) {
            struct ctlpos cp;
@@ -972,6 +1049,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                 beginbox(&cp, "Protocol options",
                          IDC_BOX_SSH3, IDC_BOXT_SSH3);
                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);
@@ -1050,6 +1128,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
            if (!strcmp(buffer, "Telnet"))
                hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
+           if (!strcmp(buffer, "Rlogin"))
+               hide(hwnd, FALSE, rloginpanelstart, rloginpanelend);
            if (!strcmp(buffer, "SSH"))
                hide(hwnd, FALSE, sshpanelstart, sshpanelend);
            if (!strcmp(buffer, "Selection"))
@@ -1078,16 +1158,19 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
            EndDialog (hwnd, 0);
            return 0;
          case IDC_PROTTELNET:
+         case IDC_PROTRLOGIN:
          case IDC_PROTSSH:
          case IDC_PROTRAW:
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED) {
                int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
                int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
-               cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
-               if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
-                   (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
-                   cfg.port = i ? 22 : 23;
+               int k = IsDlgButtonChecked (hwnd, IDC_PROTRLOGIN);
+               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)) {
+                   cfg.port = i ? 22 : j ? 23 : 513;
                    SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
                }
            }
@@ -1098,8 +1181,16 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                                sizeof(cfg.host)-1);
            break;
          case IDC_PORT:
-           if (HIWORD(wParam) == EN_CHANGE)
-               MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
+           if (HIWORD(wParam) == EN_CHANGE) {
+               GetDlgItemText (hwnd, IDC_PORT, portname, 31);
+               if (isdigit(portname[0]))
+                   MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
+               else {
+                   service = getservbyname(portname, NULL);
+                   if (service) cfg.port = ntohs(service->s_port);
+                   else cfg.port = 0;
+               }
+           }
            break;
          case IDC_SESSEDIT:
            if (HIWORD(wParam) == EN_CHANGE) {
@@ -1161,6 +1252,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                init_dlg_ctrls(hwnd);
                 if (!isdef)
                     SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
+               else
+                    SetDlgItemText(hwnd, IDC_SESSEDIT, "");
            }
            if (LOWORD(wParam) == IDC_SESSLIST) {
                /*
@@ -1374,6 +1467,21 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                HIWORD(wParam) == BN_DOUBLECLICKED)
                cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
            break;
+         case IDC_CURBLOCK:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.cursor_type = 0;
+           break;
+         case IDC_CURUNDER:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.cursor_type = 1;
+           break;
+         case IDC_CURVERT:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.cursor_type = 2;
+           break;
           case IDC_BLINKCUR:
             if (HIWORD(wParam) == BN_CLICKED ||
                 HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -1409,9 +1517,47 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
            GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
                            sizeof(cfg.termtype)-1);
            break;
+         case IDC_LGFEDIT:
+           if (HIWORD(wParam) == EN_CHANGE)
+           GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
+                           sizeof(cfg.logfilename)-1);
+           break;
+         case IDC_LGFBUTTON:
+            memset(&of, 0, sizeof(of));
+#ifdef OPENFILENAME_SIZE_VERSION_400
+            of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#else
+            of.lStructSize = sizeof(of);
+#endif
+            of.hwndOwner = hwnd;
+            of.lpstrFilter = "All Files\0*\0\0\0";
+            of.lpstrCustomFilter = NULL;
+            of.nFilterIndex = 1;
+            of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
+            of.nMaxFile = sizeof(filename);
+            of.lpstrFileTitle = NULL;
+            of.lpstrInitialDir = NULL;
+            of.lpstrTitle = "Select session log file";
+            of.Flags = 0;
+            if (GetSaveFileName(&of)) {
+                strcpy(cfg.keyfile, filename);
+                SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
+            }
+           break;
+         case IDC_LSTATOFF:
+         case IDC_LSTATASCII:
+         case IDC_LSTATRAW:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED) {
+               if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
+               if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
+               if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
+           }
+           break;
          case IDC_TSEDIT:
+         case IDC_R_TSEDIT:
            if (HIWORD(wParam) == EN_CHANGE)
-               GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
+               GetDlgItemText (hwnd, LOWORD(wParam), cfg.termspeed,
                                sizeof(cfg.termspeed)-1);
            break;
          case IDC_LOGEDIT:
@@ -1419,6 +1565,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
                                sizeof(cfg.username)-1);
            break;
+         case IDC_RLLUSEREDIT:
+           if (HIWORD(wParam) == EN_CHANGE)
+               GetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername,
+                               sizeof(cfg.localusername)-1);
+           break;
          case IDC_EMBSD:
          case IDC_EMRFC:
            cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
@@ -1497,6 +1648,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                HIWORD(wParam) == BN_DOUBLECLICKED)
                cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
            break;
+         case IDC_COMPRESS:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
+           break;
          case IDC_BUGGYMAC:
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -1603,17 +1759,15 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
                int n, i;
                cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
                n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
-               if (cfg.bold_colour && n!=22) {
-                   for (i=0; i<22; i++)
-                       if (!permcolour[i])
-                           SendDlgItemMessage (hwnd, IDC_COLOURLIST,
-                                               LB_INSERTSTRING, i,
-                                               (LPARAM) colours[i]);
-               } else if (!cfg.bold_colour && n!=12) {
-                   for (i=22; i-- ;)
-                       if (!permcolour[i])
-                           SendDlgItemMessage (hwnd, IDC_COLOURLIST,
+               if (n != 12+10*cfg.bold_colour) {
+                   for (i=n; i-- >0 ;)
+                       SendDlgItemMessage (hwnd, IDC_COLOURLIST,
                                                LB_DELETESTRING, i, 0);
+                   for (i=0; i<22; i++)
+                       if (cfg.bold_colour || permcolour[i])
+                           SendDlgItemMessage (hwnd, IDC_COLOURLIST, 
+                                               LB_ADDSTRING, 0,
+                                               (LPARAM) colours[i]);
                }
            }
            break;
@@ -1765,8 +1919,6 @@ int do_reconfig (HWND hwnd) {
     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
     if (!ret)
        cfg = backup_cfg;              /* structure copy */
-    else
-        force_normal(hwnd);
 
     return ret;
 }
@@ -1871,3 +2023,30 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
         store_host_key(host, port, keytype, keystr);
     }
 }
+
+/*
+ * 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).
+ */
+int askappend(char *filename) {
+    static const char mbtitle[] = "PuTTY Log to File";
+    static const char msgtemplate[] =
+       "The session log file \"%.*s\" already exists.\n"
+       "You can overwrite it with a new session log,\n"
+       "append your session log to the end of it,\n"
+       "or disable session logging for this session.\n"
+       "Hit Yes to wipe the file, No to append to it,\n"
+       "or Cancel to disable logging.";
+    char message[sizeof(msgtemplate) + FILENAME_MAX];
+    int mbret;
+    sprintf(message, msgtemplate, FILENAME_MAX, filename);
+
+    mbret = MessageBox(NULL, message, mbtitle,
+                       MB_ICONQUESTION | MB_YESNOCANCEL);
+    if (mbret == IDYES)
+       return 2;
+    else if (mbret == IDNO)
+       return 1;
+    else
+       return 0;
+}