]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
Saved-session name box now persists over panel switches
[PuTTY.git] / windlg.c
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <commdlg.h>
4 #include <winsock.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include "ssh.h"
9 #include "putty.h"
10 #include "win_res.h"
11
12 #define NPANELS 8
13 #define MAIN_NPANELS 8
14 #define RECONF_NPANELS 5
15
16 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
17
18 static char **events = NULL;
19 static int nevents = 0, negsize = 0;
20
21 static HWND logbox = NULL, abtbox = NULL;
22
23 static char hex[16] = "0123456789ABCDEF";
24
25 static void mungestr(char *in, char *out) {
26     int candot = 0;
27
28     while (*in) {
29         if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
30             *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
31             *out++ = '%';
32             *out++ = hex[((unsigned char)*in) >> 4];
33             *out++ = hex[((unsigned char)*in) & 15];
34         } else
35             *out++ = *in;
36         in++;
37         candot = 1;
38     }
39     *out = '\0';
40     return;
41 }
42
43 static void unmungestr(char *in, char *out) {
44     while (*in) {
45         if (*in == '%' && in[1] && in[2]) {
46             int i, j;
47
48             i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
49             j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
50
51             *out++ = (i<<4) + j;
52             in += 3;
53         } else
54             *out++ = *in++;
55     }
56     *out = '\0';
57     return;
58 }
59
60 static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
61     RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
62 }
63
64 static void wppi(HKEY key, LPCTSTR name, int value) {
65     RegSetValueEx(key, name, 0, REG_DWORD,
66                   (CONST BYTE *)&value, sizeof(value));
67 }
68
69 static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
70                  LPTSTR val, int len) {
71     DWORD type, size;
72     size = len;
73
74     if (key == NULL ||
75         RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
76         type != REG_SZ) {
77         strncpy(val, def, len);
78         val[len-1] = '\0';
79     }
80 }
81
82 static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
83     DWORD type, val, size;
84     size = sizeof(val);
85
86     if (key == NULL ||
87         RegQueryValueEx(key, name, 0, &type,
88                         (BYTE *)&val, &size) != ERROR_SUCCESS ||
89         size != sizeof(val) || type != REG_DWORD)
90         *i = def;
91     else
92         *i = val;
93 }
94
95 static HINSTANCE hinst;
96
97 static int readytogo;
98
99 static void save_settings (char *section, int do_host) {
100     int i;
101     HKEY subkey1, sesskey;
102     char *p;
103
104     p = malloc(3*strlen(section)+1);
105     mungestr(section, p);
106     
107     if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
108         RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
109         sesskey = NULL;
110     }
111
112     free(p);
113     RegCloseKey(subkey1);
114
115     wppi (sesskey, "Present", 1);
116     if (do_host) {
117         wpps (sesskey, "HostName", cfg.host);
118         wppi (sesskey, "PortNumber", cfg.port);
119         p = "raw";
120         for (i = 0; backends[i].name != NULL; i++)
121             if (backends[i].protocol == cfg.protocol) {
122                 p = backends[i].name;
123                 break;
124             }
125         wpps (sesskey, "Protocol", p);
126     }
127     wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
128     wppi (sesskey, "WarnOnClose", !!cfg.warn_on_close);
129     wpps (sesskey, "TerminalType", cfg.termtype);
130     wpps (sesskey, "TerminalSpeed", cfg.termspeed);
131     {
132       char buf[2*sizeof(cfg.environmt)], *p, *q;
133         p = buf;
134       q = cfg.environmt;
135         while (*q) {
136             while (*q) {
137                 int c = *q++;
138                 if (c == '=' || c == ',' || c == '\\')
139                     *p++ = '\\';
140                 if (c == '\t')
141                     c = '=';
142                 *p++ = c;
143             }
144             *p++ = ',';
145             q++;
146         }
147         *p = '\0';
148         wpps (sesskey, "Environment", buf);
149     }
150     wpps (sesskey, "UserName", cfg.username);
151     wppi (sesskey, "NoPTY", cfg.nopty);
152     wppi (sesskey, "AgentFwd", cfg.agentfwd);
153     wpps (sesskey, "RemoteCmd", cfg.remote_cmd);
154     wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
155                              cfg.cipher == CIPHER_DES ? "des" : "3des");
156     wppi (sesskey, "AuthTIS", cfg.try_tis_auth);
157     wppi (sesskey, "SshProt", cfg.sshprot);
158     wpps (sesskey, "PublicKeyFile", cfg.keyfile);
159     wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
160     wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
161     wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
162     wppi (sesskey, "LinuxFunctionKeys", cfg.funky_type);
163     wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
164     wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
165     wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
166     wppi (sesskey, "AltF4", cfg.alt_f4);
167     wppi (sesskey, "AltSpace", cfg.alt_space);
168     wppi (sesskey, "LdiscTerm", cfg.ldisc_term);
169     wppi (sesskey, "BlinkCur", cfg.blink_cur);
170     wppi (sesskey, "Beep", cfg.beep);
171     wppi (sesskey, "ScrollbackLines", cfg.savelines);
172     wppi (sesskey, "DECOriginMode", cfg.dec_om);
173     wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
174     wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
175     wppi (sesskey, "WinNameAlways", cfg.win_name_always);
176     wppi (sesskey, "TermWidth", cfg.width);
177     wppi (sesskey, "TermHeight", cfg.height);
178     wpps (sesskey, "Font", cfg.font);
179     wppi (sesskey, "FontIsBold", cfg.fontisbold);
180     wppi (sesskey, "FontCharSet", cfg.fontcharset);
181     wppi (sesskey, "FontHeight", cfg.fontheight);
182     wppi (sesskey, "FontVTMode", cfg.vtmode);
183     wppi (sesskey, "TryPalette", cfg.try_palette);
184     wppi (sesskey, "BoldAsColour", cfg.bold_colour);
185     for (i=0; i<22; i++) {
186         char buf[20], buf2[30];
187         sprintf(buf, "Colour%d", i);
188         sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
189                 cfg.colours[i][1], cfg.colours[i][2]);
190         wpps (sesskey, buf, buf2);
191     }
192     wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
193     for (i=0; i<256; i+=32) {
194         char buf[20], buf2[256];
195         int j;
196         sprintf(buf, "Wordness%d", i);
197         *buf2 = '\0';
198         for (j=i; j<i+32; j++) {
199             sprintf(buf2+strlen(buf2), "%s%d",
200                     (*buf2 ? "," : ""), cfg.wordness[j]);
201         }
202         wpps (sesskey, buf, buf2);
203     }
204     wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
205     wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
206     wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
207     wppi (sesskey, "ScrollBar", cfg.scrollbar);
208     wppi (sesskey, "ScrollOnKey", cfg.scroll_on_key);
209     wppi (sesskey, "LockSize", cfg.locksize);
210     wppi (sesskey, "BCE", cfg.bce);
211     wppi (sesskey, "BlinkText", cfg.blinktext);
212
213     RegCloseKey(sesskey);
214 }
215
216 static void del_session (char *section) {
217     HKEY subkey1;
218     char *p;
219
220     if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
221         return;
222
223     p = malloc(3*strlen(section)+1);
224     mungestr(section, p);
225     RegDeleteKey(subkey1, p);
226     free(p);
227
228     RegCloseKey(subkey1);
229 }
230
231 static void load_settings (char *section, int do_host) {
232     int i;
233     HKEY subkey1, sesskey;
234     char *p;
235     char prot[10];
236
237     p = malloc(3*strlen(section)+1);
238     mungestr(section, p);
239
240     if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
241         sesskey = NULL;
242     } else {
243         if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
244             sesskey = NULL;
245         }
246         RegCloseKey(subkey1);
247     }
248
249     free(p);
250
251     gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
252     gppi (sesskey, "PortNumber", default_port, &cfg.port);
253
254     gpps (sesskey, "Protocol", "default", prot, 10);
255     cfg.protocol = default_protocol;
256     for (i = 0; backends[i].name != NULL; i++)
257         if (!strcmp(prot, backends[i].name)) {
258             cfg.protocol = backends[i].protocol;
259             break;
260         }
261
262     gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
263     gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
264     gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
265           sizeof(cfg.termtype));
266     gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
267           sizeof(cfg.termspeed));
268     {
269       char buf[2*sizeof(cfg.environmt)], *p, *q;
270         gpps (sesskey, "Environment", "", buf, sizeof(buf));
271         p = buf;
272         q = cfg.environmt;
273         while (*p) {
274             while (*p && *p != ',') {
275                 int c = *p++;
276                 if (c == '=')
277                     c = '\t';
278                 if (c == '\\')
279                     c = *p++;
280                 *q++ = c;
281             }
282             if (*p == ',') p++;
283             *q++ = '\0';
284         }
285         *q = '\0';
286     }
287     gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
288     gppi (sesskey, "NoPTY", 0, &cfg.nopty);
289     gppi (sesskey, "AgentFwd", 0, &cfg.agentfwd);
290     gpps (sesskey, "RemoteCmd", "", cfg.remote_cmd, sizeof(cfg.remote_cmd));
291     {
292         char cipher[10];
293         gpps (sesskey, "Cipher", "3des", cipher, 10);
294         if (!strcmp(cipher, "blowfish"))
295             cfg.cipher = CIPHER_BLOWFISH;
296         else if (!strcmp(cipher, "des"))
297             cfg.cipher = CIPHER_DES;
298         else
299             cfg.cipher = CIPHER_3DES;
300     }
301     gppi (sesskey, "SshProt", 1, &cfg.sshprot);
302     gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
303     gpps (sesskey, "PublicKeyFile", "", cfg.keyfile, sizeof(cfg.keyfile));
304     gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
305     gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
306     gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
307     gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type);
308     gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
309     gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
310     gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
311     gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
312     gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
313     gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
314     gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur);
315     gppi (sesskey, "Beep", 1, &cfg.beep);
316     gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
317     gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
318     gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
319     gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
320     gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
321     gppi (sesskey, "TermWidth", 80, &cfg.width);
322     gppi (sesskey, "TermHeight", 24, &cfg.height);
323     gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
324     gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
325     gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
326     gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
327     gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
328     gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
329     gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
330     for (i=0; i<22; i++) {
331         static char *defaults[] = {
332             "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
333             "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
334             "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
335             "85,85,255", "187,0,187", "255,85,255", "0,187,187",
336             "85,255,255", "187,187,187", "255,255,255"
337         };
338         char buf[20], buf2[30];
339         int c0, c1, c2;
340         sprintf(buf, "Colour%d", i);
341         gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
342         if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
343             cfg.colours[i][0] = c0;
344             cfg.colours[i][1] = c1;
345             cfg.colours[i][2] = c2;
346         }
347     }
348     gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
349     for (i=0; i<256; i+=32) {
350         static char *defaults[] = {
351             "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
352             "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
353             "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
354             "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
355             "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
356             "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
357             "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
358             "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
359         };
360         char buf[20], buf2[256], *p;
361         int j;
362         sprintf(buf, "Wordness%d", i);
363         gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
364         p = buf2;
365         for (j=i; j<i+32; j++) {
366             char *q = p;
367             while (*p && *p != ',') p++;
368             if (*p == ',') *p++ = '\0';
369             cfg.wordness[j] = atoi(q);
370         }
371     }
372     gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
373     gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
374     gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
375     gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar);
376     gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key);
377     gppi (sesskey, "LockSize", 0, &cfg.locksize);
378     gppi (sesskey, "BCE", 0, &cfg.bce);
379     gppi (sesskey, "BlinkText", 0, &cfg.blinktext);
380
381     RegCloseKey(sesskey);
382 }
383
384 static void force_normal(HWND hwnd)
385 {
386 static int recurse = 0;
387
388     WINDOWPLACEMENT wp;
389
390     if(recurse) return;
391     recurse = 1;
392
393     wp.length = sizeof(wp);
394     if (GetWindowPlacement(hwnd, &wp))
395     {
396         wp.showCmd = SW_SHOWNORMAL;
397         SetWindowPlacement(hwnd, &wp);
398     }
399     recurse = 0;
400 }
401
402 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
403     BOOL ok;
404     int n;
405     n = GetDlgItemInt (hwnd, id, &ok, FALSE);
406     if (ok)
407         *result = n;
408 }
409
410 static int CALLBACK LogProc (HWND hwnd, UINT msg,
411                              WPARAM wParam, LPARAM lParam) {
412     int i;
413
414     switch (msg) {
415       case WM_INITDIALOG:
416         for (i=0; i<nevents; i++)
417             SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
418                                 0, (LPARAM)events[i]);
419         return 1;
420 /*      case WM_CTLCOLORDLG: */
421 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
422       case WM_COMMAND:
423         switch (LOWORD(wParam)) {
424           case IDOK:
425             logbox = NULL;
426             DestroyWindow (hwnd);
427             return 0;
428         }
429         return 0;
430       case WM_CLOSE:
431         logbox = NULL;
432         DestroyWindow (hwnd);
433         return 0;
434     }
435     return 0;
436 }
437
438 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
439                                  WPARAM wParam, LPARAM lParam) {
440     switch (msg) {
441       case WM_INITDIALOG:
442         return 1;
443       case WM_COMMAND:
444         switch (LOWORD(wParam)) {
445           case IDOK:
446             abtbox = NULL;
447             DestroyWindow (hwnd);
448             return 0;
449         }
450         return 0;
451       case WM_CLOSE:
452         abtbox = NULL;
453         DestroyWindow (hwnd);
454         return 0;
455     }
456     return 0;
457 }
458
459 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
460                                WPARAM wParam, LPARAM lParam) {
461     switch (msg) {
462       case WM_INITDIALOG:
463         SetDlgItemText (hwnd, IDA_VERSION, ver);
464         return 1;
465 /*      case WM_CTLCOLORDLG: */
466 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
467 /*      case WM_CTLCOLORSTATIC: */
468 /*      SetBkColor ((HDC)wParam, RGB(192,192,192)); */
469 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
470       case WM_COMMAND:
471         switch (LOWORD(wParam)) {
472           case IDOK:
473             abtbox = NULL;
474             DestroyWindow (hwnd);
475             return 0;
476           case IDA_LICENCE:
477             EnableWindow(hwnd, 0);
478             DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
479                        NULL, LicenceProc);
480             EnableWindow(hwnd, 1);
481             return 0;
482         }
483         return 0;
484       case WM_CLOSE:
485         abtbox = NULL;
486         DestroyWindow (hwnd);
487         return 0;
488     }
489     return 0;
490 }
491
492 static int GeneralPanelProc (HWND hwnd, UINT msg,
493                              WPARAM wParam, LPARAM lParam) {
494     switch (msg) {
495       case WM_INITDIALOG:
496         SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
497         return 1;
498 /*      case WM_CTLCOLORDLG: */
499 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
500 /*      case WM_CTLCOLORSTATIC: */
501 /*      case WM_CTLCOLORBTN: */
502 /*      SetBkColor ((HDC)wParam, RGB(192,192,192)); */
503 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
504       case WM_CLOSE:
505         DestroyWindow (hwnd);
506         return 1;
507     }
508     return 0;
509 }
510
511 static char savedsession[2048];
512
513 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
514                                     WPARAM wParam, LPARAM lParam) {
515     int i;
516
517     switch (msg) {
518       case WM_INITDIALOG:
519         SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
520         SetDlgItemText (hwnd, IDC0_SESSEDIT, savedsession);
521         SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
522         for (i = 0; i < nsessions; i++)
523             SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
524                                 0, (LPARAM) (sessions[i]));
525         CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
526                           cfg.protocol==PROT_SSH ? IDC0_PROTSSH : 
527                           cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
528         CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
529         CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
530         break;
531       case WM_LBUTTONUP:
532         /*
533          * Button release should trigger WM_OK if there was a
534          * previous double click on the session list.
535          */
536         ReleaseCapture();
537         if (readytogo)
538             SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
539         break;
540       case WM_COMMAND:
541         switch (LOWORD(wParam)) {
542           case IDC0_PROTTELNET:
543           case IDC0_PROTSSH:
544           case IDC0_PROTRAW:
545             if (HIWORD(wParam) == BN_CLICKED ||
546                 HIWORD(wParam) == BN_DOUBLECLICKED) {
547                 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
548                 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
549                 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
550                 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
551                     (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
552                     cfg.port = i ? 22 : 23;
553                     SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
554                 }
555             }
556             break;
557           case IDC0_HOST:
558             if (HIWORD(wParam) == EN_CHANGE)
559                 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
560                                 sizeof(cfg.host)-1);
561             break;
562           case IDC0_PORT:
563             if (HIWORD(wParam) == EN_CHANGE)
564                 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
565             break;
566           case IDC0_CLOSEEXIT:
567             if (HIWORD(wParam) == BN_CLICKED ||
568                 HIWORD(wParam) == BN_DOUBLECLICKED)
569                 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
570             break;
571           case IDC0_CLOSEWARN:
572             if (HIWORD(wParam) == BN_CLICKED ||
573                 HIWORD(wParam) == BN_DOUBLECLICKED)
574                 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
575             break;
576           case IDC0_SESSEDIT:
577             if (HIWORD(wParam) == EN_CHANGE) {
578                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
579                                     (WPARAM) -1, 0);
580                 GetDlgItemText (hwnd, IDC0_SESSEDIT,
581                                 savedsession, sizeof(savedsession)-1);
582                 savedsession[sizeof(savedsession)-1] = '\0';
583             }
584             break;
585           case IDC0_SESSSAVE:
586             if (HIWORD(wParam) == BN_CLICKED ||
587                 HIWORD(wParam) == BN_DOUBLECLICKED) {
588                 /*
589                  * Save a session
590                  */
591                 char str[2048];
592                 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
593                 if (!*str) {
594                     int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
595                                                 LB_GETCURSEL, 0, 0);
596                     if (n == LB_ERR) {
597                         MessageBeep(0);
598                         break;
599                     }
600                     strcpy (str, sessions[n]);
601                 }
602                 save_settings (str, !!strcmp(str, "Default Settings"));
603                 get_sesslist (FALSE);
604                 get_sesslist (TRUE);
605                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
606                                     0, 0);
607                 for (i = 0; i < nsessions; i++)
608                     SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
609                                         0, (LPARAM) (sessions[i]));
610                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
611                                     (WPARAM) -1, 0);
612             }
613             break;
614           case IDC0_SESSLIST:
615           case IDC0_SESSLOAD:
616             if (LOWORD(wParam) == IDC0_SESSLOAD &&
617                 HIWORD(wParam) != BN_CLICKED &&
618                 HIWORD(wParam) != BN_DOUBLECLICKED)
619                 break;
620             if (LOWORD(wParam) == IDC0_SESSLIST &&
621                 HIWORD(wParam) != LBN_DBLCLK)
622                 break;
623             {
624                 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
625                                             LB_GETCURSEL, 0, 0);
626                 if (n == LB_ERR) {
627                     MessageBeep(0);
628                     break;
629                 }
630                 load_settings (sessions[n],
631                                !!strcmp(sessions[n], "Default Settings"));
632                 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
633                 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
634                 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
635                                   (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
636                                   cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
637                 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
638                 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
639                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
640                                     (WPARAM) -1, 0);
641             }
642             if (LOWORD(wParam) == IDC0_SESSLIST) {
643                 /*
644                  * A double-click on a saved session should
645                  * actually start the session, not just load it.
646                  * Unless it's Default Settings or some other
647                  * host-less set of saved settings.
648                  */
649                 if (*cfg.host) {
650                     readytogo = TRUE;
651                     SetCapture(hwnd);
652                 }
653             }
654             break;
655           case IDC0_SESSDEL:
656             if (HIWORD(wParam) == BN_CLICKED ||
657                 HIWORD(wParam) == BN_DOUBLECLICKED) {
658                 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
659                                             LB_GETCURSEL, 0, 0);
660                 if (n == LB_ERR || n == 0) {
661                     MessageBeep(0);
662                     break;
663                 }
664                 del_session(sessions[n]);
665                 get_sesslist (FALSE);
666                 get_sesslist (TRUE);
667                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
668                                     0, 0);
669                 for (i = 0; i < nsessions; i++)
670                     SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
671                                         0, (LPARAM) (sessions[i]));
672                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
673                                     (WPARAM) -1, 0);
674             }
675         }
676     }
677     return GeneralPanelProc (hwnd, msg, wParam, lParam);
678 }
679
680 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
681                                     WPARAM wParam, LPARAM lParam) {
682     switch (msg) {
683       case WM_INITDIALOG:
684         CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
685                           cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
686         CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
687                           cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
688         CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
689                           cfg.funky_type ? 
690                           (cfg.funky_type==2 ? IDC1_FUNCXTERM 
691                            : IDC1_FUNCLINUX )
692                           : IDC1_FUNCTILDE);
693         CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
694                           cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
695         CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
696                           cfg.nethack_keypad ? IDC1_KPNH :
697                           cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
698         CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
699         CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
700         CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
701         CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
702         break;
703       case WM_COMMAND:
704         if (HIWORD(wParam) == BN_CLICKED ||
705             HIWORD(wParam) == BN_DOUBLECLICKED)
706             switch (LOWORD(wParam)) {
707               case IDC1_DEL008:
708               case IDC1_DEL127:
709                 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
710                 break;
711               case IDC1_HOMETILDE:
712               case IDC1_HOMERXVT:
713                 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
714                 break;
715               case IDC1_FUNCXTERM:
716                 cfg.funky_type = 2;
717                 break;
718               case IDC1_FUNCTILDE:
719               case IDC1_FUNCLINUX:
720                 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
721                 break;
722               case IDC1_KPNORMAL:
723               case IDC1_KPAPPLIC:
724                 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
725                 cfg.nethack_keypad = FALSE;
726                 break;
727               case IDC1_KPNH:
728                 cfg.app_keypad = FALSE;
729                 cfg.nethack_keypad = TRUE;
730                 break;
731               case IDC1_CURNORMAL:
732               case IDC1_CURAPPLIC:
733                 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
734                 break;
735               case IDC1_ALTF4:
736                 if (HIWORD(wParam) == BN_CLICKED ||
737                     HIWORD(wParam) == BN_DOUBLECLICKED)
738                     cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
739                 break;
740               case IDC1_ALTSPACE:
741                 if (HIWORD(wParam) == BN_CLICKED ||
742                     HIWORD(wParam) == BN_DOUBLECLICKED)
743                     cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
744                 break;
745               case IDC1_LDISCTERM:
746                 if (HIWORD(wParam) == BN_CLICKED ||
747                     HIWORD(wParam) == BN_DOUBLECLICKED)
748                     cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
749                 break;
750               case IDC1_SCROLLKEY:
751                 if (HIWORD(wParam) == BN_CLICKED ||
752                     HIWORD(wParam) == BN_DOUBLECLICKED)
753                     cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
754                 break;
755             }
756     }
757     return GeneralPanelProc (hwnd, msg, wParam, lParam);
758 }
759
760 static void fmtfont (char *buf) {
761     sprintf (buf, "Font: %s, ", cfg.font);
762     if (cfg.fontisbold)
763         strcat(buf, "bold, ");
764     if (cfg.fontheight == 0)
765         strcat (buf, "default height");
766     else
767         sprintf (buf+strlen(buf), "%d-%s",
768                  (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
769                  (cfg.fontheight < 0 ? "pixel" : "point"));
770 }
771
772 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
773                                     WPARAM wParam, LPARAM lParam) {
774     CHOOSEFONT cf;
775     LOGFONT lf;
776     char fontstatic[256];
777
778     switch (msg) {
779       case WM_INITDIALOG:
780         CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
781         CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
782         CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
783         CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
784         SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
785         SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
786         SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
787         fmtfont (fontstatic);
788         SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
789         CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
790         CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
791         CheckDlgButton (hwnd, IDC2_SCROLLBAR, cfg.scrollbar);
792         CheckDlgButton (hwnd, IDC2_LOCKSIZE, cfg.locksize);
793         CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
794         CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
795         break;
796       case WM_COMMAND:
797         switch (LOWORD(wParam)) {
798           case IDC2_WRAPMODE:
799             if (HIWORD(wParam) == BN_CLICKED ||
800                 HIWORD(wParam) == BN_DOUBLECLICKED)
801                 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
802             break;
803           case IDC2_WINNAME:
804             if (HIWORD(wParam) == BN_CLICKED ||
805                 HIWORD(wParam) == BN_DOUBLECLICKED)
806                 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
807             break;
808           case IDC2_DECOM:
809             if (HIWORD(wParam) == BN_CLICKED ||
810                 HIWORD(wParam) == BN_DOUBLECLICKED)
811                 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
812             break;
813           case IDC2_LFHASCR:
814             if (HIWORD(wParam) == BN_CLICKED ||
815                 HIWORD(wParam) == BN_DOUBLECLICKED)
816                 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
817             break;
818           case IDC2_ROWSEDIT:
819             if (HIWORD(wParam) == EN_CHANGE)
820                 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
821             break;
822           case IDC2_COLSEDIT:
823             if (HIWORD(wParam) == EN_CHANGE)
824                 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
825             break;
826           case IDC2_SAVEEDIT:
827             if (HIWORD(wParam) == EN_CHANGE)
828                 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
829             break;
830           case IDC2_CHOOSEFONT:
831             lf.lfHeight = cfg.fontheight;
832             lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
833             lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
834             lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
835             lf.lfCharSet = cfg.fontcharset;
836             lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
837             lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
838             lf.lfQuality = DEFAULT_QUALITY;
839             lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
840             strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
841             lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
842
843             cf.lStructSize = sizeof(cf);
844             cf.hwndOwner = hwnd;
845             cf.lpLogFont = &lf;
846             cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
847                 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
848
849             if (ChooseFont (&cf)) {
850                 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
851                 cfg.font[sizeof(cfg.font)-1] = '\0';
852                 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
853                 cfg.fontcharset = lf.lfCharSet;
854                 cfg.fontheight = lf.lfHeight;
855                 fmtfont (fontstatic);
856                 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
857             }
858             break;
859            case IDC1_BLINKCUR:
860              if (HIWORD(wParam) == BN_CLICKED ||
861                  HIWORD(wParam) == BN_DOUBLECLICKED)
862                  cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
863              break;
864            case IDC1_BEEP:
865              if (HIWORD(wParam) == BN_CLICKED ||
866                  HIWORD(wParam) == BN_DOUBLECLICKED)
867                  cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
868              break;
869            case IDC2_SCROLLBAR:
870              if (HIWORD(wParam) == BN_CLICKED ||
871                  HIWORD(wParam) == BN_DOUBLECLICKED)
872                  cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC2_SCROLLBAR);
873              break;
874            case IDC2_LOCKSIZE:
875              if (HIWORD(wParam) == BN_CLICKED ||
876                  HIWORD(wParam) == BN_DOUBLECLICKED)
877                  cfg.locksize = IsDlgButtonChecked (hwnd, IDC2_LOCKSIZE);
878              break;
879            case IDC2_BLINKTEXT:
880              if (HIWORD(wParam) == BN_CLICKED ||
881                  HIWORD(wParam) == BN_DOUBLECLICKED)
882                  cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
883              break;
884            case IDC2_BCE:
885              if (HIWORD(wParam) == BN_CLICKED ||
886                  HIWORD(wParam) == BN_DOUBLECLICKED)
887                  cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
888              break;
889         }
890         break;
891     }
892     return GeneralPanelProc (hwnd, msg, wParam, lParam);
893 }
894
895 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
896                                     WPARAM wParam, LPARAM lParam) {
897     int i;
898
899     switch (msg) {
900       case WM_INITDIALOG:
901         SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
902         SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
903         SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
904         {
905           char *p = cfg.environmt;
906             while (*p) {
907                 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
908                                     (LPARAM) p);
909                 p += strlen(p)+1;
910             }
911         }
912         CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
913                           cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
914         break;
915       case WM_COMMAND:
916         switch (LOWORD(wParam)) {
917           case IDC3_TTEDIT:
918             if (HIWORD(wParam) == EN_CHANGE)
919             GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
920                             sizeof(cfg.termtype)-1);
921             break;
922           case IDC3_TSEDIT:
923             if (HIWORD(wParam) == EN_CHANGE)
924                 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
925                                 sizeof(cfg.termspeed)-1);
926             break;
927           case IDC3_LOGEDIT:
928             if (HIWORD(wParam) == EN_CHANGE)
929                 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
930                                 sizeof(cfg.username)-1);
931             break;
932           case IDC3_EMBSD:
933           case IDC3_EMRFC:
934             cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
935             break;
936           case IDC3_ENVADD:
937             if (HIWORD(wParam) == BN_CLICKED ||
938                 HIWORD(wParam) == BN_DOUBLECLICKED) {
939               char str[sizeof(cfg.environmt)];
940                 char *p;
941                 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
942                 if (!*str) {
943                     MessageBeep(0);
944                     break;
945                 }
946                 p = str + strlen(str);
947                 *p++ = '\t';
948                 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
949                 if (!*p) {
950                     MessageBeep(0);
951                     break;
952                 }
953               p = cfg.environmt;
954                 while (*p) {
955                     while (*p) p++;
956                     p++;
957                 }
958               if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
959                     strcpy (p, str);
960                     p[strlen(str)+1] = '\0';
961                     SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
962                                         0, (LPARAM)str);
963                     SetDlgItemText (hwnd, IDC3_VAREDIT, "");
964                     SetDlgItemText (hwnd, IDC3_VALEDIT, "");
965                 } else {
966                     MessageBox(hwnd, "Environment too big", "PuTTY Error",
967                                MB_OK | MB_ICONERROR);
968                 }
969             }
970             break;
971           case IDC3_ENVREMOVE:
972             if (HIWORD(wParam) != BN_CLICKED &&
973                 HIWORD(wParam) != BN_DOUBLECLICKED)
974                 break;
975             i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
976             if (i == LB_ERR)
977                 MessageBeep (0);
978             else {
979                 char *p, *q;
980
981                 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
982                                     i, 0);
983               p = cfg.environmt;
984                 while (i > 0) {
985                     if (!*p)
986                         goto disaster;
987                     while (*p) p++;
988                     p++;
989                     i--;
990                 }
991                 q = p;
992                 if (!*p)
993                     goto disaster;
994                 while (*p) p++;
995                 p++;
996                 while (*p) {
997                     while (*p)
998                         *q++ = *p++;
999                     *q++ = *p++;
1000                 }
1001                 *q = '\0';
1002                 disaster:;
1003             }
1004             break;
1005         }
1006         break;
1007     }
1008     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1009 }
1010
1011 static int CALLBACK SshProc (HWND hwnd, UINT msg,
1012                              WPARAM wParam, LPARAM lParam) {
1013     OPENFILENAME of;
1014     char filename[sizeof(cfg.keyfile)];
1015
1016     switch (msg) {
1017       case WM_INITDIALOG:
1018         SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
1019         SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
1020         CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
1021         CheckDlgButton (hwnd, IDC3_AGENTFWD, cfg.agentfwd);
1022         CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
1023                           cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
1024                           cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
1025                           IDC3_CIPHER3DES);
1026         CheckRadioButton (hwnd, IDC3_SSHPROT1, IDC3_SSHPROT2,
1027                           cfg.sshprot == 1 ? IDC3_SSHPROT1 : IDC3_SSHPROT2);
1028         CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
1029         SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1030         break;
1031       case WM_COMMAND:
1032         switch (LOWORD(wParam)) {
1033           case IDC3_TTEDIT:
1034             if (HIWORD(wParam) == EN_CHANGE)
1035             GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
1036                             sizeof(cfg.termtype)-1);
1037             break;
1038           case IDC3_LOGEDIT:
1039             if (HIWORD(wParam) == EN_CHANGE)
1040                 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
1041                                 sizeof(cfg.username)-1);
1042             break;
1043           case IDC3_NOPTY:
1044             if (HIWORD(wParam) == BN_CLICKED ||
1045                 HIWORD(wParam) == BN_DOUBLECLICKED)
1046                 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
1047             break;
1048           case IDC3_AGENTFWD:
1049             if (HIWORD(wParam) == BN_CLICKED ||
1050                 HIWORD(wParam) == BN_DOUBLECLICKED)
1051                 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC3_AGENTFWD);
1052             break;
1053           case IDC3_CIPHER3DES:
1054           case IDC3_CIPHERBLOWF:
1055           case IDC3_CIPHERDES:
1056             if (HIWORD(wParam) == BN_CLICKED ||
1057                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1058                 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
1059                     cfg.cipher = CIPHER_3DES;
1060                 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
1061                     cfg.cipher = CIPHER_BLOWFISH;
1062                 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
1063                     cfg.cipher = CIPHER_DES;
1064             }
1065             break;
1066           case IDC3_SSHPROT1:
1067           case IDC3_SSHPROT2:
1068             if (HIWORD(wParam) == BN_CLICKED ||
1069                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1070                 if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT1))
1071                     cfg.sshprot = 1;
1072                 else if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT2))
1073                     cfg.sshprot = 2;
1074             }
1075             break;
1076           case IDC3_AUTHTIS:
1077             if (HIWORD(wParam) == BN_CLICKED ||
1078                 HIWORD(wParam) == BN_DOUBLECLICKED)
1079                 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
1080             break;
1081           case IDC3_PKEDIT:
1082             if (HIWORD(wParam) == EN_CHANGE)
1083                 GetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile,
1084                                 sizeof(cfg.keyfile)-1);
1085             break;
1086           case IDC3_PKBUTTON:
1087             /*
1088              * FIXME: this crashes. Find out why.
1089              */
1090             memset(&of, 0, sizeof(of));
1091 #ifdef OPENFILENAME_SIZE_VERSION_400
1092             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1093 #else
1094             of.lStructSize = sizeof(of);
1095 #endif
1096             of.hwndOwner = hwnd;
1097             of.lpstrFilter = "All Files\0*\0\0\0";
1098             of.lpstrCustomFilter = NULL;
1099             of.nFilterIndex = 1;
1100             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1101             of.nMaxFile = sizeof(filename);
1102             of.lpstrFileTitle = NULL;
1103             of.lpstrInitialDir = NULL;
1104             of.lpstrTitle = "Select Public Key File";
1105             of.Flags = 0;
1106             if (GetOpenFileName(&of)) {
1107                 strcpy(cfg.keyfile, filename);
1108                 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1109             }
1110             break;
1111         }
1112         break;
1113     }
1114     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1115 }
1116
1117 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1118                                     WPARAM wParam, LPARAM lParam) {
1119     int i;
1120
1121     switch (msg) {
1122       case WM_INITDIALOG:
1123         CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1124                           cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1125         {
1126             static int tabs[4] = {25, 61, 96, 128};
1127             SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1128                                 (LPARAM) tabs);
1129         }
1130         for (i=0; i<256; i++) {
1131             char str[100];
1132             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1133                     (i>=0x21 && i != 0x7F) ? i : ' ',
1134                     cfg.wordness[i]);
1135             SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1136                                 (LPARAM) str);
1137         }
1138         break;
1139       case WM_COMMAND:
1140         switch (LOWORD(wParam)) {
1141           case IDC4_MBWINDOWS:
1142           case IDC4_MBXTERM:
1143             cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1144             break;
1145           case IDC4_CCSET:
1146             {
1147                 BOOL ok;
1148                 int i;
1149                 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1150
1151                 if (!ok)
1152                     MessageBeep (0);
1153                 else {
1154                     for (i=0; i<256; i++)
1155                         if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1156                                                 i, 0)) {
1157                             char str[100];
1158                             cfg.wordness[i] = n;
1159                             SendDlgItemMessage (hwnd, IDC4_CCLIST,
1160                                                 LB_DELETESTRING, i, 0);
1161                             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1162                                     (i>=0x21 && i != 0x7F) ? i : ' ',
1163                                     cfg.wordness[i]);
1164                             SendDlgItemMessage (hwnd, IDC4_CCLIST,
1165                                                 LB_INSERTSTRING, i,
1166                                                 (LPARAM)str);
1167                         }
1168                 }
1169             }
1170             break;
1171         }
1172         break;
1173     }
1174     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1175 }
1176
1177 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1178                                     WPARAM wParam, LPARAM lParam) {
1179     static const char *const colours[] = {
1180         "Default Foreground", "Default Bold Foreground",
1181         "Default Background", "Default Bold Background",
1182         "Cursor Text", "Cursor Colour",
1183         "ANSI Black", "ANSI Black Bold",
1184         "ANSI Red", "ANSI Red Bold",
1185         "ANSI Green", "ANSI Green Bold",
1186         "ANSI Yellow", "ANSI Yellow Bold",
1187         "ANSI Blue", "ANSI Blue Bold",
1188         "ANSI Magenta", "ANSI Magenta Bold",
1189         "ANSI Cyan", "ANSI Cyan Bold",
1190         "ANSI White", "ANSI White Bold"
1191     };
1192     static const int permanent[] = {
1193         TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1194         TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1195         TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1196     };
1197     switch (msg) {
1198       case WM_INITDIALOG:
1199         CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1200         CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1201         {
1202             int i;
1203             for (i=0; i<22; i++)
1204                 if (cfg.bold_colour || permanent[i])
1205                     SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1206                                         (LPARAM) colours[i]);
1207         }
1208         SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1209         SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1210         SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1211         SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1212         break;
1213       case WM_COMMAND:
1214         switch (LOWORD(wParam)) {
1215           case IDC5_BOLDCOLOUR:
1216             if (HIWORD(wParam) == BN_CLICKED ||
1217                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1218                 int n, i;
1219                 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1220                 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1221                 if (cfg.bold_colour && n!=22) {
1222                     for (i=0; i<22; i++)
1223                         if (!permanent[i])
1224                             SendDlgItemMessage (hwnd, IDC5_LIST,
1225                                                 LB_INSERTSTRING, i,
1226                                                 (LPARAM) colours[i]);
1227                 } else if (!cfg.bold_colour && n!=12) {
1228                     for (i=22; i-- ;)
1229                         if (!permanent[i])
1230                             SendDlgItemMessage (hwnd, IDC5_LIST,
1231                                                 LB_DELETESTRING, i, 0);
1232                 }
1233             }
1234             break;
1235           case IDC5_PALETTE:
1236             if (HIWORD(wParam) == BN_CLICKED ||
1237                 HIWORD(wParam) == BN_DOUBLECLICKED)
1238                 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1239             break;
1240           case IDC5_LIST:
1241             if (HIWORD(wParam) == LBN_DBLCLK ||
1242                 HIWORD(wParam) == LBN_SELCHANGE) {
1243                 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1244                                             0, 0);
1245                 if (!cfg.bold_colour)
1246                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1247                 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1248                 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1249                 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1250             }
1251             break;
1252           case IDC5_CHANGE:
1253             if (HIWORD(wParam) == BN_CLICKED ||
1254                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1255                 static CHOOSECOLOR cc;
1256                 static DWORD custom[16] = {0};   /* zero initialisers */
1257                 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1258                                             0, 0);
1259                 if (!cfg.bold_colour)
1260                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1261                 cc.lStructSize = sizeof(cc);
1262                 cc.hwndOwner = hwnd;
1263                 cc.hInstance = (HWND)hinst;
1264                 cc.lpCustColors = custom;
1265                 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1266                                     cfg.colours[i][2]);
1267                 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1268                 if (ChooseColor(&cc)) {
1269                     cfg.colours[i][0] =
1270                         (unsigned char) (cc.rgbResult & 0xFF);
1271                     cfg.colours[i][1] =
1272                         (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1273                     cfg.colours[i][2] =
1274                         (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1275                     SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1276                                    FALSE);
1277                     SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1278                                    FALSE);
1279                     SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1280                                    FALSE);
1281                 }
1282             }
1283             break;
1284         }
1285         break;
1286     }
1287     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1288 }
1289
1290 static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
1291                                   WPARAM wParam, LPARAM lParam) {
1292     switch (msg) {
1293       case WM_INITDIALOG:
1294         CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1295                           cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1296                           cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1297                           IDC6_NOXLAT);
1298         CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1299         CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
1300                           cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
1301                           cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
1302                           cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
1303                           IDC2_VTPOORMAN);
1304       case WM_COMMAND:
1305         switch (LOWORD(wParam)) {
1306           case IDC6_NOXLAT:
1307           case IDC6_KOI8WIN1251:
1308           case IDC6_88592WIN1250:
1309             cfg.xlat_enablekoiwin =
1310                 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1311             cfg.xlat_88592w1250 =
1312                 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1313             break;
1314           case IDC6_CAPSLOCKCYR:
1315             if (HIWORD(wParam) == BN_CLICKED ||
1316                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1317                 cfg.xlat_capslockcyr =
1318                     IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1319             }
1320             break;
1321           case IDC2_VTXWINDOWS:
1322           case IDC2_VTOEMANSI:
1323           case IDC2_VTOEMONLY:
1324           case IDC2_VTPOORMAN:
1325             cfg.vtmode =
1326                 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
1327                  IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
1328                  IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
1329                  VT_POORMAN);
1330             break;
1331         }
1332     }
1333     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1334 }
1335
1336 static DLGPROC panelproc[NPANELS] = {
1337     ConnectionProc, KeyboardProc, TerminalProc,
1338     TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
1339 };
1340 static char *panelids[NPANELS] = {
1341     MAKEINTRESOURCE(IDD_PANEL0),
1342     MAKEINTRESOURCE(IDD_PANEL1),
1343     MAKEINTRESOURCE(IDD_PANEL2),
1344     MAKEINTRESOURCE(IDD_PANEL3),
1345     MAKEINTRESOURCE(IDD_PANEL35),
1346     MAKEINTRESOURCE(IDD_PANEL4),
1347     MAKEINTRESOURCE(IDD_PANEL5),
1348     MAKEINTRESOURCE(IDD_PANEL6)
1349 };
1350
1351 static char *names[NPANELS] = {
1352     "Connection", "Keyboard", "Terminal", "Telnet",
1353     "SSH", "Selection", "Colours", "Translation"
1354 };
1355
1356 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1357 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1358
1359 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1360                                WPARAM wParam, LPARAM lParam,
1361                                int npanels, int *panelnums, HWND *page) {
1362     HWND hw;
1363
1364     switch (msg) {
1365       case WM_INITDIALOG:
1366         {                              /* centre the window */
1367             RECT rs, rd;
1368
1369             hw = GetDesktopWindow();
1370             if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1371                 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1372                             (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1373                             rd.right-rd.left, rd.bottom-rd.top, TRUE);
1374         }
1375         *page = NULL;
1376         {                              /* initialise the tab control */
1377             TC_ITEMHEADER tab;
1378             int i;
1379
1380             hw = GetDlgItem (hwnd, IDC_TAB);
1381             for (i=0; i<npanels; i++) {
1382                 tab.mask = TCIF_TEXT;
1383                 tab.pszText = names[panelnums[i]];
1384                 TabCtrl_InsertItem (hw, i, &tab);
1385             }
1386 /*          *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1387                                           hwnd, panelproc[panelnums[0]]);*/
1388             *page = CreateDialog (hinst, panelids[panelnums[0]],
1389                                   hwnd, panelproc[panelnums[0]]);
1390             SetWindowLong (*page, GWL_EXSTYLE,
1391                            GetWindowLong (*page, GWL_EXSTYLE) |
1392                            WS_EX_CONTROLPARENT);
1393         }
1394         SetFocus (*page);
1395         return 0;
1396       case WM_NOTIFY:
1397         if (LOWORD(wParam) == IDC_TAB &&
1398             ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1399             int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1400             if (*page)
1401                 DestroyWindow (*page);
1402 /*          *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,     
1403                                           hwnd, panelproc[panelnums[i]]);*/
1404             *page = CreateDialog (hinst, panelids[panelnums[i]],
1405                                   hwnd, panelproc[panelnums[i]]);
1406             SetWindowLong (*page, GWL_EXSTYLE,
1407                            GetWindowLong (*page, GWL_EXSTYLE) |
1408                            WS_EX_CONTROLPARENT);
1409             SetFocus (((LPNMHDR)lParam)->hwndFrom);   /* ensure focus stays */
1410             return 0;
1411         }
1412         break;
1413 /*      case WM_CTLCOLORDLG: */
1414 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
1415       case WM_COMMAND:
1416         switch (LOWORD(wParam)) {
1417           case IDOK:
1418             if (*cfg.host)
1419                 EndDialog (hwnd, 1);
1420             else
1421                 MessageBeep (0);
1422             return 0;
1423           case IDCANCEL:
1424             EndDialog (hwnd, 0);
1425             return 0;
1426         }
1427         return 0;
1428       case WM_CLOSE:
1429         EndDialog (hwnd, 0);
1430         return 0;
1431
1432         /* Grrr Explorer will maximize Dialogs! */
1433       case WM_SIZE:
1434         if (wParam == SIZE_MAXIMIZED)
1435            force_normal(hwnd);
1436         return 0;
1437     }
1438     return 0;
1439 }
1440
1441 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1442                                  WPARAM wParam, LPARAM lParam) {
1443 #if 0
1444     HWND hw;
1445     int i;
1446 #endif
1447     static HWND page = NULL;
1448
1449     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1450 #if 0
1451         /*
1452          * If the Connection panel is active and the Session List
1453          * box is selected, we treat a press of Open to have an
1454          * implicit press of Load preceding it.
1455          */
1456         hw = GetDlgItem (hwnd, IDC_TAB);
1457         i = TabCtrl_GetCurSel(hw);
1458         if (panelproc[mainp[i]] == ConnectionProc &&
1459             page && implicit_load_ok) {
1460             SendMessage (page, WM_COMMAND,
1461                          MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1462         }
1463 #endif
1464     }
1465     if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1466         EnableWindow(hwnd, 0);
1467         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1468                   GetParent(hwnd), AboutProc);
1469         EnableWindow(hwnd, 1);
1470     }
1471     return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1472                                MAIN_NPANELS, mainp, &page);
1473 }
1474
1475 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1476                                    WPARAM wParam, LPARAM lParam) {
1477     static HWND page;
1478     return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1479                                RECONF_NPANELS, reconfp, &page);
1480 }
1481
1482 void get_sesslist(int allocate) {
1483     static char *buffer;
1484     int buflen, bufsize, i, ret;
1485     char otherbuf[2048];
1486     char *p;
1487     HKEY subkey1;
1488
1489     if (allocate) {
1490         if (RegCreateKey(HKEY_CURRENT_USER,
1491                          puttystr, &subkey1) != ERROR_SUCCESS)
1492             return;
1493
1494         buflen = bufsize = 0;
1495         buffer = NULL;
1496         i = 0;
1497         do {
1498             ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1499             if (ret == ERROR_SUCCESS) {
1500                 bufsize = buflen + 2048;
1501                 buffer = srealloc(buffer, bufsize);
1502                 unmungestr(otherbuf, buffer+buflen);
1503                 buflen += strlen(buffer+buflen)+1;
1504             }
1505         } while (ret == ERROR_SUCCESS);
1506         buffer = srealloc(buffer, buflen+1);
1507         buffer[buflen] = '\0';
1508
1509         p = buffer;
1510         nsessions = 1;                 /* "Default Settings" counts as one */
1511         while (*p) {
1512             if (strcmp(p, "Default Settings"))
1513                 nsessions++;
1514             while (*p) p++;
1515             p++;
1516         }
1517
1518         sessions = smalloc(nsessions * sizeof(char *));
1519         sessions[0] = "Default Settings";
1520         p = buffer;
1521         i = 1;
1522         while (*p) {
1523             if (strcmp(p, "Default Settings"))
1524                 sessions[i++] = p;
1525             while (*p) p++;
1526             p++;
1527         }
1528     } else {
1529         sfree (buffer);
1530         sfree (sessions);
1531     }
1532 }
1533
1534 int do_config (void) {
1535     int ret;
1536
1537     get_sesslist(TRUE);
1538     savedsession[0] = '\0';
1539     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1540     get_sesslist(FALSE);
1541
1542     return ret;
1543 }
1544
1545 int do_reconfig (HWND hwnd) {
1546     Config backup_cfg;
1547     int ret;
1548
1549     backup_cfg = cfg;                  /* structure copy */
1550     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1551     if (!ret)
1552         cfg = backup_cfg;              /* structure copy */
1553     else
1554         force_normal(hwnd);
1555
1556     return ret;
1557 }
1558
1559 void do_defaults (char *session) {
1560     if (session)
1561         load_settings (session, TRUE);
1562     else
1563         load_settings ("Default Settings", FALSE);
1564 }
1565
1566 void logevent (char *string) {
1567     if (nevents >= negsize) {
1568         negsize += 64;
1569         events = srealloc (events, negsize * sizeof(*events));
1570     }
1571     events[nevents] = smalloc(1+strlen(string));
1572     strcpy (events[nevents], string);
1573     nevents++;
1574     if (logbox)
1575         SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1576                             0, (LPARAM)string);
1577 }
1578
1579 void showeventlog (HWND hwnd) {
1580     if (!logbox) {
1581         logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1582                                hwnd, LogProc);
1583         ShowWindow (logbox, SW_SHOWNORMAL);
1584     }
1585 }
1586
1587 void showabout (HWND hwnd) {
1588     if (!abtbox) {
1589         abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1590                                hwnd, AboutProc);
1591         ShowWindow (abtbox, SW_SHOWNORMAL);
1592     }
1593 }
1594
1595 void verify_ssh_host_key(char *host, char *keystr) {
1596     char *otherstr, *mungedhost;
1597     int len;
1598     HKEY rkey;
1599
1600     len = 1 + strlen(keystr);
1601
1602     /*
1603      * Now read a saved key in from the registry and see what it
1604      * says.
1605      */
1606     otherstr = smalloc(len);
1607     mungedhost = smalloc(3*strlen(host)+1);
1608     if (!otherstr || !mungedhost)
1609         fatalbox("Out of memory");
1610
1611     mungestr(host, mungedhost);
1612
1613     if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1614                      &rkey) != ERROR_SUCCESS) {
1615         if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1616                        "in the registry. There is thus no way to tell\n"
1617                        "if the remote host is what you think it is.\n"
1618                        "Connect anyway?", "PuTTY Problem",
1619                        MB_ICONWARNING | MB_YESNO) == IDNO)
1620             exit(0);
1621     } else {
1622         DWORD readlen = len;
1623         DWORD type;
1624         int ret;
1625
1626         ret = RegQueryValueEx(rkey, mungedhost, NULL,
1627                               &type, otherstr, &readlen);
1628
1629         if (ret == ERROR_MORE_DATA ||
1630             (ret == ERROR_SUCCESS && type == REG_SZ &&
1631              strcmp(otherstr, keystr))) {
1632             if (MessageBox(NULL,
1633                            "This host's host key is different from the\n"
1634                            "one cached in the registry! Someone may be\n"
1635                            "impersonating this host for malicious reasons;\n"
1636                            "alternatively, the host key may have changed\n"
1637                            "due to sloppy system administration.\n"
1638                            "Replace key in registry and connect?",
1639                            "PuTTY: Security Warning",
1640                            MB_ICONWARNING | MB_YESNO) == IDNO)
1641                 exit(0);
1642             RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1643                           strlen(keystr)+1);
1644         } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1645             if (MessageBox(NULL,
1646                            "This host's host key is not cached in the\n"
1647                            "registry. Do you want to add it to the cache\n"
1648                            "and carry on connecting?",
1649                            "PuTTY: New Host",
1650                            MB_ICONWARNING | MB_YESNO) == IDNO)
1651                 exit(0);
1652             RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1653                           strlen(keystr)+1);
1654         }
1655
1656         RegCloseKey(rkey);
1657     }
1658 }