Mark Baker's raw-TCP back end (untested and experimental as yet)
[u/mdw/putty] / windlg.c
index ecd3e5f..023ebbc 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -5,8 +5,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "putty.h"
 #include "ssh.h"
+#include "putty.h"
 #include "win_res.h"
 
 #define NPANELS 7
@@ -15,8 +15,6 @@
 
 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
 
-static void get_sesslist(int allocate);
-
 static char **negots = NULL;
 static int nnegots = 0, negsize = 0;
 static HWND logbox = NULL, abtbox = NULL;
@@ -42,8 +40,6 @@ static void mungestr(char *in, char *out) {
 }
 
 static void unmungestr(char *in, char *out) {
-    int candot = 0;
-
     while (*in) {
        if (*in == '%' && in[1] && in[2]) {
            int i, j;
@@ -95,16 +91,9 @@ static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
        *i = val;
 }
 
-typedef struct {
-    void *posn;
-    void *temp;
-    char dataspace[2048];
-} DTemplate;
-
 static HINSTANCE hinst;
 
-static char **sessions;
-static int nsessions;
+static int readytogo;
 
 static void save_settings (char *section, int do_host) {
     int i;
@@ -116,7 +105,6 @@ static void save_settings (char *section, int do_host) {
     
     if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
        RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
-       free(p);
        sesskey = NULL;
     }
 
@@ -128,15 +116,16 @@ static void save_settings (char *section, int do_host) {
        wpps (sesskey, "HostName", cfg.host);
        wppi (sesskey, "PortNumber", cfg.port);
        wpps (sesskey, "Protocol",
-             cfg.protocol == PROT_SSH ? "ssh" : "telnet");
+             cfg.protocol == PROT_SSH ? "ssh" : 
+                 cfg.protocol == PROT_TELNET ? "telnet" : "raw" );
     }
     wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
     wpps (sesskey, "TerminalType", cfg.termtype);
     wpps (sesskey, "TerminalSpeed", cfg.termspeed);
     {
-       char buf[2*sizeof(cfg.environ)], *p, *q;
+      char buf[2*sizeof(cfg.environmt)], *p, *q;
        p = buf;
-       q = cfg.environ;
+      q = cfg.environmt;
        while (*q) {
            while (*q) {
                int c = *q++;
@@ -153,6 +142,9 @@ static void save_settings (char *section, int do_host) {
        wpps (sesskey, "Environment", buf);
     }
     wpps (sesskey, "UserName", cfg.username);
+    wppi (sesskey, "NoPTY", cfg.nopty);
+    wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
+                             cfg.cipher == CIPHER_DES ? "des" : "3des");
     wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
     wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
     wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
@@ -162,6 +154,7 @@ static void save_settings (char *section, int do_host) {
     wppi (sesskey, "ScrollbackLines", cfg.savelines);
     wppi (sesskey, "DECOriginMode", cfg.dec_om);
     wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
+    wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
     wppi (sesskey, "WinNameAlways", cfg.win_name_always);
     wppi (sesskey, "TermWidth", cfg.width);
     wppi (sesskey, "TermHeight", cfg.height);
@@ -213,42 +206,44 @@ static void load_settings (char *section, int do_host) {
     int i;
     HKEY subkey1, sesskey;
     char *p;
+    char prot[10];
 
     p = malloc(3*strlen(section)+1);
     mungestr(section, p);
-    
-    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS ||
-       RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
-       free(p);
+
+    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
        sesskey = NULL;
+    } else {
+       if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
+           sesskey = NULL;
+       }
+       RegCloseKey(subkey1);
     }
 
     free(p);
-    RegCloseKey(subkey1);
 
-    if (do_host) {
-       char prot[10];
-       gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
-       gppi (sesskey, "PortNumber", 23, &cfg.port);
-       gpps (sesskey, "Protocol", "telnet", prot, 10);
-       if (!strcmp(prot, "ssh"))
-           cfg.protocol = PROT_SSH;
-       else
-           cfg.protocol = PROT_TELNET;
-    } else {
-       cfg.port = 23;
-       *cfg.host = '\0';
-    }
+    gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
+    gppi (sesskey, "PortNumber", default_port, &cfg.port);
+    gpps (sesskey, "Protocol", "default", prot, 10);
+    if (!strcmp(prot, "ssh"))
+       cfg.protocol = PROT_SSH;
+    else if (!strcmp(prot, "telnet"))
+       cfg.protocol = PROT_TELNET;
+    else if (!strcmp(prot, "raw"))
+       cfg.protocol = PROT_RAW;
+    else
+       cfg.protocol = default_protocol;
+
     gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
     gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
          sizeof(cfg.termtype));
     gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
          sizeof(cfg.termspeed));
     {
-       char buf[2*sizeof(cfg.environ)], *p, *q;
+      char buf[2*sizeof(cfg.environmt)], *p, *q;
        gpps (sesskey, "Environment", "", buf, sizeof(buf));
        p = buf;
-       q = cfg.environ;
+      q = cfg.environmt;
        while (*p) {
            while (*p && *p != ',') {
                int c = *p++;
@@ -264,6 +259,17 @@ static void load_settings (char *section, int do_host) {
        *q = '\0';
     }
     gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
+    gppi (sesskey, "NoPTY", 0, &cfg.nopty);
+    {
+       char cipher[10];
+       gpps (sesskey, "Cipher", "3des", cipher, 10);
+       if (!strcmp(cipher, "blowfish"))
+           cfg.cipher = CIPHER_BLOWFISH;
+       else if (!strcmp(cipher, "des"))
+           cfg.cipher = CIPHER_DES;
+       else
+           cfg.cipher = CIPHER_3DES;
+    }
     gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
     gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
     gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
@@ -273,6 +279,7 @@ static void load_settings (char *section, int do_host) {
     gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
     gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
     gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
+    gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
     gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
     gppi (sesskey, "TermWidth", 80, &cfg.width);
     gppi (sesskey, "TermHeight", 24, &cfg.height);
@@ -359,10 +366,32 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg,
     return 0;
 }
 
+static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
+                                WPARAM wParam, LPARAM lParam) {
+    switch (msg) {
+      case WM_INITDIALOG:
+       return 1;
+      case WM_COMMAND:
+       switch (LOWORD(wParam)) {
+         case IDOK:
+           abtbox = NULL;
+           DestroyWindow (hwnd);
+           return 0;
+       }
+       return 0;
+      case WM_CLOSE:
+       abtbox = NULL;
+       DestroyWindow (hwnd);
+       return 0;
+    }
+    return 0;
+}
+
 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
                               WPARAM wParam, LPARAM lParam) {
     switch (msg) {
       case WM_INITDIALOG:
+        SetDlgItemText (hwnd, IDA_VERSION, ver);
        return 1;
 /*      case WM_CTLCOLORDLG: */
 /*     return (int) GetStockObject (LTGRAY_BRUSH); */
@@ -378,7 +407,7 @@ static int CALLBACK AboutProc (HWND hwnd, UINT msg,
          case IDA_LICENCE:
            EnableWindow(hwnd, 0);
            DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
-                      NULL, AboutProc);
+                      NULL, LicenceProc);
            EnableWindow(hwnd, 1);
            return 0;
        }
@@ -421,18 +450,30 @@ static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
        for (i = 0; i < nsessions; i++)
            SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
                                0, (LPARAM) (sessions[i]));
-       CheckRadioButton (hwnd, IDC0_PROTTELNET, IDC0_PROTSSH,
-                         cfg.protocol==PROT_SSH ? IDC0_PROTSSH : IDC0_PROTTELNET);
+       CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
+                         cfg.protocol==PROT_SSH ? IDC0_PROTSSH : 
+                         cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
        CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
        break;
+      case WM_LBUTTONUP:
+        /*
+         * Button release should trigger WM_OK if there was a
+         * previous double click on the session list.
+         */
+        ReleaseCapture();
+        if (readytogo)
+            SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
+        break;
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
          case IDC0_PROTTELNET:
          case IDC0_PROTSSH:
+         case IDC0_PROTRAW:
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED) {
                int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
-               cfg.protocol = i ? PROT_SSH : PROT_TELNET;
+               int j = IsDlgButtonChecked (hwnd, IDC0_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;
@@ -508,9 +549,9 @@ static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
                               !!strcmp(sessions[n], "Default Settings"));
                SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
                SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
-               CheckRadioButton (hwnd, IDC0_PROTTELNET, IDC0_PROTSSH,
+               CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
                                  (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
-                                  IDC0_PROTTELNET));
+                                 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
                CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
                SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
                                    (WPARAM) -1, 0);
@@ -522,8 +563,10 @@ static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
                 * Unless it's Default Settings or some other
                 * host-less set of saved settings.
                 */
-               if (*cfg.host)
-                   SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
+               if (*cfg.host) {
+                    readytogo = TRUE;
+                    SetCapture(hwnd);
+                }
            }
            break;
          case IDC0_SESSDEL:
@@ -618,6 +661,7 @@ static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
        CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
        CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
        CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
+       CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
        SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
        SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
        SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
@@ -646,6 +690,11 @@ static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
                HIWORD(wParam) == BN_DOUBLECLICKED)
                cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
            break;
+         case IDC2_LFHASCR:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
+           break;
          case IDC2_ROWSEDIT:
            if (HIWORD(wParam) == EN_CHANGE)
                MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
@@ -712,7 +761,7 @@ static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
        SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
        SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
        {
-           char *p = cfg.environ;
+          char *p = cfg.environmt;
            while (*p) {
                SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
                                    (LPARAM) p);
@@ -746,7 +795,7 @@ static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
          case IDC3_ENVADD:
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED) {
-               char str[sizeof(cfg.environ)];
+              char str[sizeof(cfg.environmt)];
                char *p;
                GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
                if (!*str) {
@@ -760,12 +809,12 @@ static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
                    MessageBeep(0);
                    break;
                }
-               p = cfg.environ;
+              p = cfg.environmt;
                while (*p) {
                    while (*p) p++;
                    p++;
                }
-               if ((p-cfg.environ) + strlen(str) + 2 < sizeof(cfg.environ)) {
+              if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
                    strcpy (p, str);
                    p[strlen(str)+1] = '\0';
                    SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
@@ -790,7 +839,7 @@ static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
 
                SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
                                    i, 0);
-               p = cfg.environ;
+              p = cfg.environmt;
                while (i > 0) {
                    if (!*p)
                        goto disaster;
@@ -824,6 +873,12 @@ static int CALLBACK SshProc (HWND hwnd, UINT msg,
       case WM_INITDIALOG:
        SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
        SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
+       CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
+       CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
+                         cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
+                         cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
+
+                         IDC3_CIPHER3DES);
        break;
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
@@ -837,6 +892,24 @@ static int CALLBACK SshProc (HWND hwnd, UINT msg,
                GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
                                sizeof(cfg.username)-1);
            break;
+         case IDC3_NOPTY:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
+           break;
+         case IDC3_CIPHER3DES:
+         case IDC3_CIPHERBLOWF:
+         case IDC3_CIPHERDES:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED) {
+               if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
+                   cfg.cipher = CIPHER_3DES;
+               else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
+                   cfg.cipher = CIPHER_BLOWFISH;
+               else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
+                   cfg.cipher = CIPHER_DES;
+           }
+           break;
        }
        break;
     }
@@ -1016,7 +1089,6 @@ static int CALLBACK ColourProc (HWND hwnd, UINT msg,
     return GeneralPanelProc (hwnd, msg, wParam, lParam);
 }
 
-static DTemplate negot, main, reconf, panels[NPANELS];
 static DLGPROC panelproc[NPANELS] = {
     ConnectionProc, KeyboardProc, TerminalProc,
     TelnetProc, SshProc, SelectionProc, ColourProc
@@ -1154,7 +1226,7 @@ static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
                               RECONF_NPANELS, reconfp, &page);
 }
 
-static void get_sesslist(int allocate) {
+void get_sesslist(int allocate) {
     static char *buffer;
     int buflen, bufsize, i, ret;
     char otherbuf[2048];