]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
ca8691414df76ccc6238da895cf5d85b7a1e1ac5
[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             SetActiveWindow(hwnd);
482             return 0;
483         }
484         return 0;
485       case WM_CLOSE:
486         abtbox = NULL;
487         DestroyWindow (hwnd);
488         return 0;
489     }
490     return 0;
491 }
492
493 static int GeneralPanelProc (HWND hwnd, UINT msg,
494                              WPARAM wParam, LPARAM lParam) {
495     switch (msg) {
496       case WM_INITDIALOG:
497         SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
498         return 1;
499 /*      case WM_CTLCOLORDLG: */
500 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
501 /*      case WM_CTLCOLORSTATIC: */
502 /*      case WM_CTLCOLORBTN: */
503 /*      SetBkColor ((HDC)wParam, RGB(192,192,192)); */
504 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
505       case WM_CLOSE:
506         DestroyWindow (hwnd);
507         return 1;
508     }
509     return 0;
510 }
511
512 static char savedsession[2048];
513
514 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
515                                     WPARAM wParam, LPARAM lParam) {
516     int i;
517
518     switch (msg) {
519       case WM_INITDIALOG:
520         SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
521         SetDlgItemText (hwnd, IDC0_SESSEDIT, savedsession);
522         SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
523         for (i = 0; i < nsessions; i++)
524             SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
525                                 0, (LPARAM) (sessions[i]));
526         CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
527                           cfg.protocol==PROT_SSH ? IDC0_PROTSSH : 
528                           cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
529         CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
530         CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
531         break;
532       case WM_LBUTTONUP:
533         /*
534          * Button release should trigger WM_OK if there was a
535          * previous double click on the session list.
536          */
537         ReleaseCapture();
538         if (readytogo)
539             SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
540         break;
541       case WM_COMMAND:
542         switch (LOWORD(wParam)) {
543           case IDC0_PROTTELNET:
544           case IDC0_PROTSSH:
545           case IDC0_PROTRAW:
546             if (HIWORD(wParam) == BN_CLICKED ||
547                 HIWORD(wParam) == BN_DOUBLECLICKED) {
548                 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
549                 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
550                 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
551                 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
552                     (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
553                     cfg.port = i ? 22 : 23;
554                     SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
555                 }
556             }
557             break;
558           case IDC0_HOST:
559             if (HIWORD(wParam) == EN_CHANGE)
560                 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
561                                 sizeof(cfg.host)-1);
562             break;
563           case IDC0_PORT:
564             if (HIWORD(wParam) == EN_CHANGE)
565                 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
566             break;
567           case IDC0_CLOSEEXIT:
568             if (HIWORD(wParam) == BN_CLICKED ||
569                 HIWORD(wParam) == BN_DOUBLECLICKED)
570                 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
571             break;
572           case IDC0_CLOSEWARN:
573             if (HIWORD(wParam) == BN_CLICKED ||
574                 HIWORD(wParam) == BN_DOUBLECLICKED)
575                 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
576             break;
577           case IDC0_SESSEDIT:
578             if (HIWORD(wParam) == EN_CHANGE) {
579                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
580                                     (WPARAM) -1, 0);
581                 GetDlgItemText (hwnd, IDC0_SESSEDIT,
582                                 savedsession, sizeof(savedsession)-1);
583                 savedsession[sizeof(savedsession)-1] = '\0';
584             }
585             break;
586           case IDC0_SESSSAVE:
587             if (HIWORD(wParam) == BN_CLICKED ||
588                 HIWORD(wParam) == BN_DOUBLECLICKED) {
589                 /*
590                  * Save a session
591                  */
592                 char str[2048];
593                 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
594                 if (!*str) {
595                     int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
596                                                 LB_GETCURSEL, 0, 0);
597                     if (n == LB_ERR) {
598                         MessageBeep(0);
599                         break;
600                     }
601                     strcpy (str, sessions[n]);
602                 }
603                 save_settings (str, !!strcmp(str, "Default Settings"));
604                 get_sesslist (FALSE);
605                 get_sesslist (TRUE);
606                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
607                                     0, 0);
608                 for (i = 0; i < nsessions; i++)
609                     SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
610                                         0, (LPARAM) (sessions[i]));
611                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
612                                     (WPARAM) -1, 0);
613             }
614             break;
615           case IDC0_SESSLIST:
616           case IDC0_SESSLOAD:
617             if (LOWORD(wParam) == IDC0_SESSLOAD &&
618                 HIWORD(wParam) != BN_CLICKED &&
619                 HIWORD(wParam) != BN_DOUBLECLICKED)
620                 break;
621             if (LOWORD(wParam) == IDC0_SESSLIST &&
622                 HIWORD(wParam) != LBN_DBLCLK)
623                 break;
624             {
625                 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
626                                             LB_GETCURSEL, 0, 0);
627                 if (n == LB_ERR) {
628                     MessageBeep(0);
629                     break;
630                 }
631                 load_settings (sessions[n],
632                                !!strcmp(sessions[n], "Default Settings"));
633                 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
634                 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
635                 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
636                                   (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
637                                   cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
638                 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
639                 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
640                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
641                                     (WPARAM) -1, 0);
642             }
643             if (LOWORD(wParam) == IDC0_SESSLIST) {
644                 /*
645                  * A double-click on a saved session should
646                  * actually start the session, not just load it.
647                  * Unless it's Default Settings or some other
648                  * host-less set of saved settings.
649                  */
650                 if (*cfg.host) {
651                     readytogo = TRUE;
652                     SetCapture(hwnd);
653                 }
654             }
655             break;
656           case IDC0_SESSDEL:
657             if (HIWORD(wParam) == BN_CLICKED ||
658                 HIWORD(wParam) == BN_DOUBLECLICKED) {
659                 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
660                                             LB_GETCURSEL, 0, 0);
661                 if (n == LB_ERR || n == 0) {
662                     MessageBeep(0);
663                     break;
664                 }
665                 del_session(sessions[n]);
666                 get_sesslist (FALSE);
667                 get_sesslist (TRUE);
668                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
669                                     0, 0);
670                 for (i = 0; i < nsessions; i++)
671                     SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
672                                         0, (LPARAM) (sessions[i]));
673                 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
674                                     (WPARAM) -1, 0);
675             }
676         }
677     }
678     return GeneralPanelProc (hwnd, msg, wParam, lParam);
679 }
680
681 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
682                                     WPARAM wParam, LPARAM lParam) {
683     switch (msg) {
684       case WM_INITDIALOG:
685         CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
686                           cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
687         CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
688                           cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
689         CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
690                           cfg.funky_type ? 
691                           (cfg.funky_type==2 ? IDC1_FUNCXTERM 
692                            : IDC1_FUNCLINUX )
693                           : IDC1_FUNCTILDE);
694         CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
695                           cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
696         CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
697                           cfg.nethack_keypad ? IDC1_KPNH :
698                           cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
699         CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
700         CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
701         CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
702         CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
703         break;
704       case WM_COMMAND:
705         if (HIWORD(wParam) == BN_CLICKED ||
706             HIWORD(wParam) == BN_DOUBLECLICKED)
707             switch (LOWORD(wParam)) {
708               case IDC1_DEL008:
709               case IDC1_DEL127:
710                 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
711                 break;
712               case IDC1_HOMETILDE:
713               case IDC1_HOMERXVT:
714                 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
715                 break;
716               case IDC1_FUNCXTERM:
717                 cfg.funky_type = 2;
718                 break;
719               case IDC1_FUNCTILDE:
720               case IDC1_FUNCLINUX:
721                 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
722                 break;
723               case IDC1_KPNORMAL:
724               case IDC1_KPAPPLIC:
725                 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
726                 cfg.nethack_keypad = FALSE;
727                 break;
728               case IDC1_KPNH:
729                 cfg.app_keypad = FALSE;
730                 cfg.nethack_keypad = TRUE;
731                 break;
732               case IDC1_CURNORMAL:
733               case IDC1_CURAPPLIC:
734                 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
735                 break;
736               case IDC1_ALTF4:
737                 if (HIWORD(wParam) == BN_CLICKED ||
738                     HIWORD(wParam) == BN_DOUBLECLICKED)
739                     cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
740                 break;
741               case IDC1_ALTSPACE:
742                 if (HIWORD(wParam) == BN_CLICKED ||
743                     HIWORD(wParam) == BN_DOUBLECLICKED)
744                     cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
745                 break;
746               case IDC1_LDISCTERM:
747                 if (HIWORD(wParam) == BN_CLICKED ||
748                     HIWORD(wParam) == BN_DOUBLECLICKED)
749                     cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
750                 break;
751               case IDC1_SCROLLKEY:
752                 if (HIWORD(wParam) == BN_CLICKED ||
753                     HIWORD(wParam) == BN_DOUBLECLICKED)
754                     cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
755                 break;
756             }
757     }
758     return GeneralPanelProc (hwnd, msg, wParam, lParam);
759 }
760
761 static void fmtfont (char *buf) {
762     sprintf (buf, "Font: %s, ", cfg.font);
763     if (cfg.fontisbold)
764         strcat(buf, "bold, ");
765     if (cfg.fontheight == 0)
766         strcat (buf, "default height");
767     else
768         sprintf (buf+strlen(buf), "%d-%s",
769                  (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
770                  (cfg.fontheight < 0 ? "pixel" : "point"));
771 }
772
773 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
774                                     WPARAM wParam, LPARAM lParam) {
775     CHOOSEFONT cf;
776     LOGFONT lf;
777     char fontstatic[256];
778
779     switch (msg) {
780       case WM_INITDIALOG:
781         CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
782         CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
783         CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
784         CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
785         SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
786         SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
787         SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
788         fmtfont (fontstatic);
789         SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
790         CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
791         CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
792         CheckDlgButton (hwnd, IDC2_SCROLLBAR, cfg.scrollbar);
793         CheckDlgButton (hwnd, IDC2_LOCKSIZE, cfg.locksize);
794         CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
795         CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
796         break;
797       case WM_COMMAND:
798         switch (LOWORD(wParam)) {
799           case IDC2_WRAPMODE:
800             if (HIWORD(wParam) == BN_CLICKED ||
801                 HIWORD(wParam) == BN_DOUBLECLICKED)
802                 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
803             break;
804           case IDC2_WINNAME:
805             if (HIWORD(wParam) == BN_CLICKED ||
806                 HIWORD(wParam) == BN_DOUBLECLICKED)
807                 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
808             break;
809           case IDC2_DECOM:
810             if (HIWORD(wParam) == BN_CLICKED ||
811                 HIWORD(wParam) == BN_DOUBLECLICKED)
812                 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
813             break;
814           case IDC2_LFHASCR:
815             if (HIWORD(wParam) == BN_CLICKED ||
816                 HIWORD(wParam) == BN_DOUBLECLICKED)
817                 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
818             break;
819           case IDC2_ROWSEDIT:
820             if (HIWORD(wParam) == EN_CHANGE)
821                 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
822             break;
823           case IDC2_COLSEDIT:
824             if (HIWORD(wParam) == EN_CHANGE)
825                 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
826             break;
827           case IDC2_SAVEEDIT:
828             if (HIWORD(wParam) == EN_CHANGE)
829                 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
830             break;
831           case IDC2_CHOOSEFONT:
832             lf.lfHeight = cfg.fontheight;
833             lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
834             lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
835             lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
836             lf.lfCharSet = cfg.fontcharset;
837             lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
838             lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
839             lf.lfQuality = DEFAULT_QUALITY;
840             lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
841             strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
842             lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
843
844             cf.lStructSize = sizeof(cf);
845             cf.hwndOwner = hwnd;
846             cf.lpLogFont = &lf;
847             cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
848                 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
849
850             if (ChooseFont (&cf)) {
851                 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
852                 cfg.font[sizeof(cfg.font)-1] = '\0';
853                 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
854                 cfg.fontcharset = lf.lfCharSet;
855                 cfg.fontheight = lf.lfHeight;
856                 fmtfont (fontstatic);
857                 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
858             }
859             break;
860            case IDC1_BLINKCUR:
861              if (HIWORD(wParam) == BN_CLICKED ||
862                  HIWORD(wParam) == BN_DOUBLECLICKED)
863                  cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
864              break;
865            case IDC1_BEEP:
866              if (HIWORD(wParam) == BN_CLICKED ||
867                  HIWORD(wParam) == BN_DOUBLECLICKED)
868                  cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
869              break;
870            case IDC2_SCROLLBAR:
871              if (HIWORD(wParam) == BN_CLICKED ||
872                  HIWORD(wParam) == BN_DOUBLECLICKED)
873                  cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC2_SCROLLBAR);
874              break;
875            case IDC2_LOCKSIZE:
876              if (HIWORD(wParam) == BN_CLICKED ||
877                  HIWORD(wParam) == BN_DOUBLECLICKED)
878                  cfg.locksize = IsDlgButtonChecked (hwnd, IDC2_LOCKSIZE);
879              break;
880            case IDC2_BLINKTEXT:
881              if (HIWORD(wParam) == BN_CLICKED ||
882                  HIWORD(wParam) == BN_DOUBLECLICKED)
883                  cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
884              break;
885            case IDC2_BCE:
886              if (HIWORD(wParam) == BN_CLICKED ||
887                  HIWORD(wParam) == BN_DOUBLECLICKED)
888                  cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
889              break;
890         }
891         break;
892     }
893     return GeneralPanelProc (hwnd, msg, wParam, lParam);
894 }
895
896 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
897                                     WPARAM wParam, LPARAM lParam) {
898     int i;
899
900     switch (msg) {
901       case WM_INITDIALOG:
902         SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
903         SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
904         SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
905         {
906           char *p = cfg.environmt;
907             while (*p) {
908                 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
909                                     (LPARAM) p);
910                 p += strlen(p)+1;
911             }
912         }
913         CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
914                           cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
915         break;
916       case WM_COMMAND:
917         switch (LOWORD(wParam)) {
918           case IDC3_TTEDIT:
919             if (HIWORD(wParam) == EN_CHANGE)
920             GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
921                             sizeof(cfg.termtype)-1);
922             break;
923           case IDC3_TSEDIT:
924             if (HIWORD(wParam) == EN_CHANGE)
925                 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
926                                 sizeof(cfg.termspeed)-1);
927             break;
928           case IDC3_LOGEDIT:
929             if (HIWORD(wParam) == EN_CHANGE)
930                 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
931                                 sizeof(cfg.username)-1);
932             break;
933           case IDC3_EMBSD:
934           case IDC3_EMRFC:
935             cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
936             break;
937           case IDC3_ENVADD:
938             if (HIWORD(wParam) == BN_CLICKED ||
939                 HIWORD(wParam) == BN_DOUBLECLICKED) {
940               char str[sizeof(cfg.environmt)];
941                 char *p;
942                 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
943                 if (!*str) {
944                     MessageBeep(0);
945                     break;
946                 }
947                 p = str + strlen(str);
948                 *p++ = '\t';
949                 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
950                 if (!*p) {
951                     MessageBeep(0);
952                     break;
953                 }
954               p = cfg.environmt;
955                 while (*p) {
956                     while (*p) p++;
957                     p++;
958                 }
959               if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
960                     strcpy (p, str);
961                     p[strlen(str)+1] = '\0';
962                     SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
963                                         0, (LPARAM)str);
964                     SetDlgItemText (hwnd, IDC3_VAREDIT, "");
965                     SetDlgItemText (hwnd, IDC3_VALEDIT, "");
966                 } else {
967                     MessageBox(hwnd, "Environment too big", "PuTTY Error",
968                                MB_OK | MB_ICONERROR);
969                 }
970             }
971             break;
972           case IDC3_ENVREMOVE:
973             if (HIWORD(wParam) != BN_CLICKED &&
974                 HIWORD(wParam) != BN_DOUBLECLICKED)
975                 break;
976             i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
977             if (i == LB_ERR)
978                 MessageBeep (0);
979             else {
980                 char *p, *q;
981
982                 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
983                                     i, 0);
984               p = cfg.environmt;
985                 while (i > 0) {
986                     if (!*p)
987                         goto disaster;
988                     while (*p) p++;
989                     p++;
990                     i--;
991                 }
992                 q = p;
993                 if (!*p)
994                     goto disaster;
995                 while (*p) p++;
996                 p++;
997                 while (*p) {
998                     while (*p)
999                         *q++ = *p++;
1000                     *q++ = *p++;
1001                 }
1002                 *q = '\0';
1003                 disaster:;
1004             }
1005             break;
1006         }
1007         break;
1008     }
1009     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1010 }
1011
1012 static int CALLBACK SshProc (HWND hwnd, UINT msg,
1013                              WPARAM wParam, LPARAM lParam) {
1014     OPENFILENAME of;
1015     char filename[sizeof(cfg.keyfile)];
1016
1017     switch (msg) {
1018       case WM_INITDIALOG:
1019         SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
1020         SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
1021         CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
1022         CheckDlgButton (hwnd, IDC3_AGENTFWD, cfg.agentfwd);
1023         CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
1024                           cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
1025                           cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
1026                           IDC3_CIPHER3DES);
1027         CheckRadioButton (hwnd, IDC3_SSHPROT1, IDC3_SSHPROT2,
1028                           cfg.sshprot == 1 ? IDC3_SSHPROT1 : IDC3_SSHPROT2);
1029         CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
1030         SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1031         break;
1032       case WM_COMMAND:
1033         switch (LOWORD(wParam)) {
1034           case IDC3_TTEDIT:
1035             if (HIWORD(wParam) == EN_CHANGE)
1036             GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
1037                             sizeof(cfg.termtype)-1);
1038             break;
1039           case IDC3_LOGEDIT:
1040             if (HIWORD(wParam) == EN_CHANGE)
1041                 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
1042                                 sizeof(cfg.username)-1);
1043             break;
1044           case IDC3_NOPTY:
1045             if (HIWORD(wParam) == BN_CLICKED ||
1046                 HIWORD(wParam) == BN_DOUBLECLICKED)
1047                 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
1048             break;
1049           case IDC3_AGENTFWD:
1050             if (HIWORD(wParam) == BN_CLICKED ||
1051                 HIWORD(wParam) == BN_DOUBLECLICKED)
1052                 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC3_AGENTFWD);
1053             break;
1054           case IDC3_CIPHER3DES:
1055           case IDC3_CIPHERBLOWF:
1056           case IDC3_CIPHERDES:
1057             if (HIWORD(wParam) == BN_CLICKED ||
1058                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1059                 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
1060                     cfg.cipher = CIPHER_3DES;
1061                 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
1062                     cfg.cipher = CIPHER_BLOWFISH;
1063                 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
1064                     cfg.cipher = CIPHER_DES;
1065             }
1066             break;
1067           case IDC3_SSHPROT1:
1068           case IDC3_SSHPROT2:
1069             if (HIWORD(wParam) == BN_CLICKED ||
1070                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1071                 if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT1))
1072                     cfg.sshprot = 1;
1073                 else if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT2))
1074                     cfg.sshprot = 2;
1075             }
1076             break;
1077           case IDC3_AUTHTIS:
1078             if (HIWORD(wParam) == BN_CLICKED ||
1079                 HIWORD(wParam) == BN_DOUBLECLICKED)
1080                 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
1081             break;
1082           case IDC3_PKEDIT:
1083             if (HIWORD(wParam) == EN_CHANGE)
1084                 GetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile,
1085                                 sizeof(cfg.keyfile)-1);
1086             break;
1087           case IDC3_PKBUTTON:
1088             /*
1089              * FIXME: this crashes. Find out why.
1090              */
1091             memset(&of, 0, sizeof(of));
1092 #ifdef OPENFILENAME_SIZE_VERSION_400
1093             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1094 #else
1095             of.lStructSize = sizeof(of);
1096 #endif
1097             of.hwndOwner = hwnd;
1098             of.lpstrFilter = "All Files\0*\0\0\0";
1099             of.lpstrCustomFilter = NULL;
1100             of.nFilterIndex = 1;
1101             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1102             of.nMaxFile = sizeof(filename);
1103             of.lpstrFileTitle = NULL;
1104             of.lpstrInitialDir = NULL;
1105             of.lpstrTitle = "Select Public Key File";
1106             of.Flags = 0;
1107             if (GetOpenFileName(&of)) {
1108                 strcpy(cfg.keyfile, filename);
1109                 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1110             }
1111             break;
1112         }
1113         break;
1114     }
1115     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1116 }
1117
1118 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1119                                     WPARAM wParam, LPARAM lParam) {
1120     int i;
1121
1122     switch (msg) {
1123       case WM_INITDIALOG:
1124         CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1125                           cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1126         {
1127             static int tabs[4] = {25, 61, 96, 128};
1128             SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1129                                 (LPARAM) tabs);
1130         }
1131         for (i=0; i<256; i++) {
1132             char str[100];
1133             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1134                     (i>=0x21 && i != 0x7F) ? i : ' ',
1135                     cfg.wordness[i]);
1136             SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1137                                 (LPARAM) str);
1138         }
1139         break;
1140       case WM_COMMAND:
1141         switch (LOWORD(wParam)) {
1142           case IDC4_MBWINDOWS:
1143           case IDC4_MBXTERM:
1144             cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1145             break;
1146           case IDC4_CCSET:
1147             {
1148                 BOOL ok;
1149                 int i;
1150                 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1151
1152                 if (!ok)
1153                     MessageBeep (0);
1154                 else {
1155                     for (i=0; i<256; i++)
1156                         if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1157                                                 i, 0)) {
1158                             char str[100];
1159                             cfg.wordness[i] = n;
1160                             SendDlgItemMessage (hwnd, IDC4_CCLIST,
1161                                                 LB_DELETESTRING, i, 0);
1162                             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1163                                     (i>=0x21 && i != 0x7F) ? i : ' ',
1164                                     cfg.wordness[i]);
1165                             SendDlgItemMessage (hwnd, IDC4_CCLIST,
1166                                                 LB_INSERTSTRING, i,
1167                                                 (LPARAM)str);
1168                         }
1169                 }
1170             }
1171             break;
1172         }
1173         break;
1174     }
1175     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1176 }
1177
1178 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1179                                     WPARAM wParam, LPARAM lParam) {
1180     static const char *const colours[] = {
1181         "Default Foreground", "Default Bold Foreground",
1182         "Default Background", "Default Bold Background",
1183         "Cursor Text", "Cursor Colour",
1184         "ANSI Black", "ANSI Black Bold",
1185         "ANSI Red", "ANSI Red Bold",
1186         "ANSI Green", "ANSI Green Bold",
1187         "ANSI Yellow", "ANSI Yellow Bold",
1188         "ANSI Blue", "ANSI Blue Bold",
1189         "ANSI Magenta", "ANSI Magenta Bold",
1190         "ANSI Cyan", "ANSI Cyan Bold",
1191         "ANSI White", "ANSI White Bold"
1192     };
1193     static const int permanent[] = {
1194         TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1195         TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1196         TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1197     };
1198     switch (msg) {
1199       case WM_INITDIALOG:
1200         CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1201         CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1202         {
1203             int i;
1204             for (i=0; i<22; i++)
1205                 if (cfg.bold_colour || permanent[i])
1206                     SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1207                                         (LPARAM) colours[i]);
1208         }
1209         SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1210         SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1211         SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1212         SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1213         break;
1214       case WM_COMMAND:
1215         switch (LOWORD(wParam)) {
1216           case IDC5_BOLDCOLOUR:
1217             if (HIWORD(wParam) == BN_CLICKED ||
1218                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1219                 int n, i;
1220                 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1221                 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1222                 if (cfg.bold_colour && n!=22) {
1223                     for (i=0; i<22; i++)
1224                         if (!permanent[i])
1225                             SendDlgItemMessage (hwnd, IDC5_LIST,
1226                                                 LB_INSERTSTRING, i,
1227                                                 (LPARAM) colours[i]);
1228                 } else if (!cfg.bold_colour && n!=12) {
1229                     for (i=22; i-- ;)
1230                         if (!permanent[i])
1231                             SendDlgItemMessage (hwnd, IDC5_LIST,
1232                                                 LB_DELETESTRING, i, 0);
1233                 }
1234             }
1235             break;
1236           case IDC5_PALETTE:
1237             if (HIWORD(wParam) == BN_CLICKED ||
1238                 HIWORD(wParam) == BN_DOUBLECLICKED)
1239                 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1240             break;
1241           case IDC5_LIST:
1242             if (HIWORD(wParam) == LBN_DBLCLK ||
1243                 HIWORD(wParam) == LBN_SELCHANGE) {
1244                 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1245                                             0, 0);
1246                 if (!cfg.bold_colour)
1247                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1248                 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1249                 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1250                 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1251             }
1252             break;
1253           case IDC5_CHANGE:
1254             if (HIWORD(wParam) == BN_CLICKED ||
1255                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1256                 static CHOOSECOLOR cc;
1257                 static DWORD custom[16] = {0};   /* zero initialisers */
1258                 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1259                                             0, 0);
1260                 if (!cfg.bold_colour)
1261                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1262                 cc.lStructSize = sizeof(cc);
1263                 cc.hwndOwner = hwnd;
1264                 cc.hInstance = (HWND)hinst;
1265                 cc.lpCustColors = custom;
1266                 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1267                                     cfg.colours[i][2]);
1268                 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1269                 if (ChooseColor(&cc)) {
1270                     cfg.colours[i][0] =
1271                         (unsigned char) (cc.rgbResult & 0xFF);
1272                     cfg.colours[i][1] =
1273                         (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1274                     cfg.colours[i][2] =
1275                         (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1276                     SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1277                                    FALSE);
1278                     SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1279                                    FALSE);
1280                     SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1281                                    FALSE);
1282                 }
1283             }
1284             break;
1285         }
1286         break;
1287     }
1288     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1289 }
1290
1291 static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
1292                                   WPARAM wParam, LPARAM lParam) {
1293     switch (msg) {
1294       case WM_INITDIALOG:
1295         CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1296                           cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1297                           cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1298                           IDC6_NOXLAT);
1299         CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1300         CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
1301                           cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
1302                           cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
1303                           cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
1304                           IDC2_VTPOORMAN);
1305       case WM_COMMAND:
1306         switch (LOWORD(wParam)) {
1307           case IDC6_NOXLAT:
1308           case IDC6_KOI8WIN1251:
1309           case IDC6_88592WIN1250:
1310             cfg.xlat_enablekoiwin =
1311                 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1312             cfg.xlat_88592w1250 =
1313                 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1314             break;
1315           case IDC6_CAPSLOCKCYR:
1316             if (HIWORD(wParam) == BN_CLICKED ||
1317                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1318                 cfg.xlat_capslockcyr =
1319                     IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1320             }
1321             break;
1322           case IDC2_VTXWINDOWS:
1323           case IDC2_VTOEMANSI:
1324           case IDC2_VTOEMONLY:
1325           case IDC2_VTPOORMAN:
1326             cfg.vtmode =
1327                 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
1328                  IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
1329                  IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
1330                  VT_POORMAN);
1331             break;
1332         }
1333     }
1334     return GeneralPanelProc (hwnd, msg, wParam, lParam);
1335 }
1336
1337 static DLGPROC panelproc[NPANELS] = {
1338     ConnectionProc, KeyboardProc, TerminalProc,
1339     TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
1340 };
1341 static char *panelids[NPANELS] = {
1342     MAKEINTRESOURCE(IDD_PANEL0),
1343     MAKEINTRESOURCE(IDD_PANEL1),
1344     MAKEINTRESOURCE(IDD_PANEL2),
1345     MAKEINTRESOURCE(IDD_PANEL3),
1346     MAKEINTRESOURCE(IDD_PANEL35),
1347     MAKEINTRESOURCE(IDD_PANEL4),
1348     MAKEINTRESOURCE(IDD_PANEL5),
1349     MAKEINTRESOURCE(IDD_PANEL6)
1350 };
1351
1352 static char *names[NPANELS] = {
1353     "Connection", "Keyboard", "Terminal", "Telnet",
1354     "SSH", "Selection", "Colours", "Translation"
1355 };
1356
1357 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1358 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1359
1360 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1361                                WPARAM wParam, LPARAM lParam,
1362                                int npanels, int *panelnums, HWND *page) {
1363     HWND hw;
1364
1365     switch (msg) {
1366       case WM_INITDIALOG:
1367         {                              /* centre the window */
1368             RECT rs, rd;
1369
1370             hw = GetDesktopWindow();
1371             if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1372                 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1373                             (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1374                             rd.right-rd.left, rd.bottom-rd.top, TRUE);
1375         }
1376         *page = NULL;
1377         {                              /* initialise the tab control */
1378             TC_ITEMHEADER tab;
1379             int i;
1380
1381             hw = GetDlgItem (hwnd, IDC_TAB);
1382             for (i=0; i<npanels; i++) {
1383                 tab.mask = TCIF_TEXT;
1384                 tab.pszText = names[panelnums[i]];
1385                 TabCtrl_InsertItem (hw, i, &tab);
1386             }
1387 /*          *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1388                                           hwnd, panelproc[panelnums[0]]);*/
1389             *page = CreateDialog (hinst, panelids[panelnums[0]],
1390                                   hwnd, panelproc[panelnums[0]]);
1391             SetWindowLong (*page, GWL_EXSTYLE,
1392                            GetWindowLong (*page, GWL_EXSTYLE) |
1393                            WS_EX_CONTROLPARENT);
1394         }
1395         SetFocus (*page);
1396         return 0;
1397       case WM_NOTIFY:
1398         if (LOWORD(wParam) == IDC_TAB &&
1399             ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1400             int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1401             if (*page)
1402                 DestroyWindow (*page);
1403 /*          *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,     
1404                                           hwnd, panelproc[panelnums[i]]);*/
1405             *page = CreateDialog (hinst, panelids[panelnums[i]],
1406                                   hwnd, panelproc[panelnums[i]]);
1407             SetWindowLong (*page, GWL_EXSTYLE,
1408                            GetWindowLong (*page, GWL_EXSTYLE) |
1409                            WS_EX_CONTROLPARENT);
1410             SetFocus (((LPNMHDR)lParam)->hwndFrom);   /* ensure focus stays */
1411             return 0;
1412         }
1413         break;
1414 /*      case WM_CTLCOLORDLG: */
1415 /*      return (int) GetStockObject (LTGRAY_BRUSH); */
1416       case WM_COMMAND:
1417         switch (LOWORD(wParam)) {
1418           case IDOK:
1419             if (*cfg.host)
1420                 EndDialog (hwnd, 1);
1421             else
1422                 MessageBeep (0);
1423             return 0;
1424           case IDCANCEL:
1425             EndDialog (hwnd, 0);
1426             return 0;
1427         }
1428         return 0;
1429       case WM_CLOSE:
1430         EndDialog (hwnd, 0);
1431         return 0;
1432
1433         /* Grrr Explorer will maximize Dialogs! */
1434       case WM_SIZE:
1435         if (wParam == SIZE_MAXIMIZED)
1436            force_normal(hwnd);
1437         return 0;
1438     }
1439     return 0;
1440 }
1441
1442 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1443                                  WPARAM wParam, LPARAM lParam) {
1444 #if 0
1445     HWND hw;
1446     int i;
1447 #endif
1448     static HWND page = NULL;
1449
1450     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1451 #if 0
1452         /*
1453          * If the Connection panel is active and the Session List
1454          * box is selected, we treat a press of Open to have an
1455          * implicit press of Load preceding it.
1456          */
1457         hw = GetDlgItem (hwnd, IDC_TAB);
1458         i = TabCtrl_GetCurSel(hw);
1459         if (panelproc[mainp[i]] == ConnectionProc &&
1460             page && implicit_load_ok) {
1461             SendMessage (page, WM_COMMAND,
1462                          MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1463         }
1464 #endif
1465     }
1466     if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1467         EnableWindow(hwnd, 0);
1468         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1469                   GetParent(hwnd), AboutProc);
1470         EnableWindow(hwnd, 1);
1471         SetActiveWindow(hwnd);
1472     }
1473     return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1474                                MAIN_NPANELS, mainp, &page);
1475 }
1476
1477 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1478                                    WPARAM wParam, LPARAM lParam) {
1479     static HWND page;
1480     return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1481                                RECONF_NPANELS, reconfp, &page);
1482 }
1483
1484 void get_sesslist(int allocate) {
1485     static char *buffer;
1486     int buflen, bufsize, i, ret;
1487     char otherbuf[2048];
1488     char *p;
1489     HKEY subkey1;
1490
1491     if (allocate) {
1492         if (RegCreateKey(HKEY_CURRENT_USER,
1493                          puttystr, &subkey1) != ERROR_SUCCESS)
1494             return;
1495
1496         buflen = bufsize = 0;
1497         buffer = NULL;
1498         i = 0;
1499         do {
1500             ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1501             if (ret == ERROR_SUCCESS) {
1502                 bufsize = buflen + 2048;
1503                 buffer = srealloc(buffer, bufsize);
1504                 unmungestr(otherbuf, buffer+buflen);
1505                 buflen += strlen(buffer+buflen)+1;
1506             }
1507         } while (ret == ERROR_SUCCESS);
1508         buffer = srealloc(buffer, buflen+1);
1509         buffer[buflen] = '\0';
1510
1511         p = buffer;
1512         nsessions = 1;                 /* "Default Settings" counts as one */
1513         while (*p) {
1514             if (strcmp(p, "Default Settings"))
1515                 nsessions++;
1516             while (*p) p++;
1517             p++;
1518         }
1519
1520         sessions = smalloc(nsessions * sizeof(char *));
1521         sessions[0] = "Default Settings";
1522         p = buffer;
1523         i = 1;
1524         while (*p) {
1525             if (strcmp(p, "Default Settings"))
1526                 sessions[i++] = p;
1527             while (*p) p++;
1528             p++;
1529         }
1530     } else {
1531         sfree (buffer);
1532         sfree (sessions);
1533     }
1534 }
1535
1536 int do_config (void) {
1537     int ret;
1538
1539     get_sesslist(TRUE);
1540     savedsession[0] = '\0';
1541     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1542     get_sesslist(FALSE);
1543
1544     return ret;
1545 }
1546
1547 int do_reconfig (HWND hwnd) {
1548     Config backup_cfg;
1549     int ret;
1550
1551     backup_cfg = cfg;                  /* structure copy */
1552     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1553     if (!ret)
1554         cfg = backup_cfg;              /* structure copy */
1555     else
1556         force_normal(hwnd);
1557
1558     return ret;
1559 }
1560
1561 void do_defaults (char *session) {
1562     if (session)
1563         load_settings (session, TRUE);
1564     else
1565         load_settings ("Default Settings", FALSE);
1566 }
1567
1568 void logevent (char *string) {
1569     if (nevents >= negsize) {
1570         negsize += 64;
1571         events = srealloc (events, negsize * sizeof(*events));
1572     }
1573     events[nevents] = smalloc(1+strlen(string));
1574     strcpy (events[nevents], string);
1575     nevents++;
1576     if (logbox)
1577         SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1578                             0, (LPARAM)string);
1579 }
1580
1581 void showeventlog (HWND hwnd) {
1582     if (!logbox) {
1583         logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1584                                hwnd, LogProc);
1585         ShowWindow (logbox, SW_SHOWNORMAL);
1586     }
1587 }
1588
1589 void showabout (HWND hwnd) {
1590     if (!abtbox) {
1591         abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1592                                hwnd, AboutProc);
1593         ShowWindow (abtbox, SW_SHOWNORMAL);
1594     }
1595 }
1596
1597 void verify_ssh_host_key(char *host, char *keystr) {
1598     char *otherstr, *mungedhost;
1599     int len;
1600     HKEY rkey;
1601
1602     len = 1 + strlen(keystr);
1603
1604     /*
1605      * Now read a saved key in from the registry and see what it
1606      * says.
1607      */
1608     otherstr = smalloc(len);
1609     mungedhost = smalloc(3*strlen(host)+1);
1610     if (!otherstr || !mungedhost)
1611         fatalbox("Out of memory");
1612
1613     mungestr(host, mungedhost);
1614
1615     if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1616                      &rkey) != ERROR_SUCCESS) {
1617         if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1618                        "in the registry. There is thus no way to tell\n"
1619                        "if the remote host is what you think it is.\n"
1620                        "Connect anyway?", "PuTTY Problem",
1621                        MB_ICONWARNING | MB_YESNO) == IDNO)
1622             exit(0);
1623     } else {
1624         DWORD readlen = len;
1625         DWORD type;
1626         int ret;
1627
1628         ret = RegQueryValueEx(rkey, mungedhost, NULL,
1629                               &type, otherstr, &readlen);
1630
1631         if (ret == ERROR_MORE_DATA ||
1632             (ret == ERROR_SUCCESS && type == REG_SZ &&
1633              strcmp(otherstr, keystr))) {
1634             if (MessageBox(NULL,
1635                            "This host's host key is different from the\n"
1636                            "one cached in the registry! Someone may be\n"
1637                            "impersonating this host for malicious reasons;\n"
1638                            "alternatively, the host key may have changed\n"
1639                            "due to sloppy system administration.\n"
1640                            "Replace key in registry and connect?",
1641                            "PuTTY: Security Warning",
1642                            MB_ICONWARNING | MB_YESNO) == IDNO)
1643                 exit(0);
1644             RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1645                           strlen(keystr)+1);
1646         } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1647             if (MessageBox(NULL,
1648                            "This host's host key is not cached in the\n"
1649                            "registry. Do you want to add it to the cache\n"
1650                            "and carry on connecting?",
1651                            "PuTTY: New Host",
1652                            MB_ICONWARNING | MB_YESNO) == IDNO)
1653                 exit(0);
1654             RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1655                           strlen(keystr)+1);
1656         }
1657
1658         RegCloseKey(rkey);
1659     }
1660 }