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