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