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