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