]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
Make keyboard-interactive authentication configurable off. (This is
[PuTTY.git] / windlg.c
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <commdlg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <ctype.h>
7 #include <time.h>
8
9 #include "ssh.h"
10 #include "putty.h"
11 #include "winstuff.h"
12 #include "win_res.h"
13 #include "storage.h"
14
15 static char **events = NULL;
16 static int nevents = 0, negsize = 0;
17
18 static int readytogo;
19 static int sesslist_has_focus;
20
21 static struct prefslist cipherlist;
22
23 void force_normal(HWND hwnd)
24 {
25     static int recurse = 0;
26
27     WINDOWPLACEMENT wp;
28
29     if (recurse)
30         return;
31     recurse = 1;
32
33     wp.length = sizeof(wp);
34     if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) {
35         wp.showCmd = SW_SHOWNORMAL;
36         SetWindowPlacement(hwnd, &wp);
37     }
38     recurse = 0;
39 }
40
41 static void MyGetDlgItemInt(HWND hwnd, int id, int *result)
42 {
43     BOOL ok;
44     int n;
45     n = GetDlgItemInt(hwnd, id, &ok, FALSE);
46     if (ok)
47         *result = n;
48 }
49
50 static void MyGetDlgItemFlt(HWND hwnd, int id, int *result, int scale)
51 {
52     char text[80];
53     BOOL ok;
54     ok = GetDlgItemText(hwnd, id, text, sizeof(text) - 1);
55     if (ok && text[0])
56         *result = (int) (scale * atof(text));
57 }
58
59 static void MySetDlgItemFlt(HWND hwnd, int id, double value)
60 {
61     char text[80];
62     sprintf(text, "%g", value);
63     SetDlgItemText(hwnd, id, text);
64 }
65
66 static int CALLBACK LogProc(HWND hwnd, UINT msg,
67                             WPARAM wParam, LPARAM lParam)
68 {
69     int i;
70
71     switch (msg) {
72       case WM_INITDIALOG:
73         {
74             static int tabs[4] = { 78, 108 };
75             SendDlgItemMessage(hwnd, IDN_LIST, LB_SETTABSTOPS, 2,
76                                (LPARAM) tabs);
77         }
78         for (i = 0; i < nevents; i++)
79             SendDlgItemMessage(hwnd, IDN_LIST, LB_ADDSTRING,
80                                0, (LPARAM) events[i]);
81         return 1;
82       case WM_COMMAND:
83         switch (LOWORD(wParam)) {
84           case IDOK:
85           case IDCANCEL:
86             logbox = NULL;
87             SetActiveWindow(GetParent(hwnd));
88             DestroyWindow(hwnd);
89             return 0;
90           case IDN_COPY:
91             if (HIWORD(wParam) == BN_CLICKED ||
92                 HIWORD(wParam) == BN_DOUBLECLICKED) {
93                 int selcount;
94                 int *selitems;
95                 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
96                                               LB_GETSELCOUNT, 0, 0);
97                 if (selcount == 0) {   /* don't even try to copy zero items */
98                     MessageBeep(0);
99                     break;
100                 }
101
102                 selitems = smalloc(selcount * sizeof(int));
103                 if (selitems) {
104                     int count = SendDlgItemMessage(hwnd, IDN_LIST,
105                                                    LB_GETSELITEMS,
106                                                    selcount,
107                                                    (LPARAM) selitems);
108                     int i;
109                     int size;
110                     char *clipdata;
111                     static unsigned char sel_nl[] = SEL_NL;
112
113                     if (count == 0) {  /* can't copy zero stuff */
114                         MessageBeep(0);
115                         break;
116                     }
117
118                     size = 0;
119                     for (i = 0; i < count; i++)
120                         size +=
121                             strlen(events[selitems[i]]) + sizeof(sel_nl);
122
123                     clipdata = smalloc(size);
124                     if (clipdata) {
125                         char *p = clipdata;
126                         for (i = 0; i < count; i++) {
127                             char *q = events[selitems[i]];
128                             int qlen = strlen(q);
129                             memcpy(p, q, qlen);
130                             p += qlen;
131                             memcpy(p, sel_nl, sizeof(sel_nl));
132                             p += sizeof(sel_nl);
133                         }
134                         write_aclip(clipdata, size, TRUE);
135                         sfree(clipdata);
136                     }
137                     sfree(selitems);
138
139                     for (i = 0; i < nevents; i++)
140                         SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
141                                            FALSE, i);
142                 }
143             }
144             return 0;
145         }
146         return 0;
147       case WM_CLOSE:
148         logbox = NULL;
149         SetActiveWindow(GetParent(hwnd));
150         DestroyWindow(hwnd);
151         return 0;
152     }
153     return 0;
154 }
155
156 static int CALLBACK LicenceProc(HWND hwnd, UINT msg,
157                                 WPARAM wParam, LPARAM lParam)
158 {
159     switch (msg) {
160       case WM_INITDIALOG:
161         return 1;
162       case WM_COMMAND:
163         switch (LOWORD(wParam)) {
164           case IDOK:
165             EndDialog(hwnd, 1);
166             return 0;
167         }
168         return 0;
169       case WM_CLOSE:
170         EndDialog(hwnd, 1);
171         return 0;
172     }
173     return 0;
174 }
175
176 static int CALLBACK AboutProc(HWND hwnd, UINT msg,
177                               WPARAM wParam, LPARAM lParam)
178 {
179     switch (msg) {
180       case WM_INITDIALOG:
181         SetDlgItemText(hwnd, IDA_VERSION, ver);
182         return 1;
183       case WM_COMMAND:
184         switch (LOWORD(wParam)) {
185           case IDOK:
186           case IDCANCEL:
187             EndDialog(hwnd, TRUE);
188             return 0;
189           case IDA_LICENCE:
190             EnableWindow(hwnd, 0);
191             DialogBox(hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
192                       NULL, LicenceProc);
193             EnableWindow(hwnd, 1);
194             SetActiveWindow(hwnd);
195             return 0;
196
197           case IDA_WEB:
198             /* Load web browser */
199             ShellExecute(hwnd, "open",
200                          "http://www.chiark.greenend.org.uk/~sgtatham/putty/",
201                          0, 0, SW_SHOWDEFAULT);
202             return 0;
203         }
204         return 0;
205       case WM_CLOSE:
206         EndDialog(hwnd, TRUE);
207         return 0;
208     }
209     return 0;
210 }
211
212 /*
213  * Null dialog procedure.
214  */
215 static int CALLBACK NullDlgProc(HWND hwnd, UINT msg,
216                                 WPARAM wParam, LPARAM lParam)
217 {
218     return 0;
219 }
220
221 static char savedsession[2048];
222
223 enum { IDCX_ABOUT =
224         IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
225
226     sessionpanelstart,
227     IDC_TITLE_SESSION,
228     IDC_BOX_SESSION1,
229     IDC_BOX_SESSION2,
230     IDC_BOX_SESSION3,
231     IDC_HOSTSTATIC,
232     IDC_HOST,
233     IDC_PORTSTATIC,
234     IDC_PORT,
235     IDC_PROTSTATIC,
236     IDC_PROTRAW,
237     IDC_PROTTELNET,
238     IDC_PROTRLOGIN,
239     IDC_PROTSSH,
240     IDC_SESSSTATIC,
241     IDC_SESSEDIT,
242     IDC_SESSLIST,
243     IDC_SESSLOAD,
244     IDC_SESSSAVE,
245     IDC_SESSDEL,
246     IDC_CLOSEEXIT,
247     IDC_COEALWAYS,
248     IDC_COENEVER,
249     IDC_COENORMAL,
250     sessionpanelend,
251
252     loggingpanelstart,
253     IDC_TITLE_LOGGING,
254     IDC_BOX_LOGGING1,
255     IDC_LSTATSTATIC,
256     IDC_LSTATOFF,
257     IDC_LSTATASCII,
258     IDC_LSTATRAW,
259     IDC_LGFSTATIC,
260     IDC_LGFEDIT,
261     IDC_LGFBUTTON,
262     IDC_LGFEXPLAIN,
263     IDC_LSTATXIST,
264     IDC_LSTATXOVR,
265     IDC_LSTATXAPN,
266     IDC_LSTATXASK,
267     loggingpanelend,
268
269     keyboardpanelstart,
270     IDC_TITLE_KEYBOARD,
271     IDC_BOX_KEYBOARD1,
272     IDC_BOX_KEYBOARD2,
273     IDC_BOX_KEYBOARD3,
274     IDC_DELSTATIC,
275     IDC_DEL008,
276     IDC_DEL127,
277     IDC_HOMESTATIC,
278     IDC_HOMETILDE,
279     IDC_HOMERXVT,
280     IDC_FUNCSTATIC,
281     IDC_FUNCTILDE,
282     IDC_FUNCLINUX,
283     IDC_FUNCXTERM,
284     IDC_FUNCVT400,
285     IDC_FUNCVT100P,
286     IDC_FUNCSCO,
287     IDC_KPSTATIC,
288     IDC_KPNORMAL,
289     IDC_KPAPPLIC,
290     IDC_KPNH,
291     IDC_NOAPPLICK,
292     IDC_NOAPPLICC,
293     IDC_CURSTATIC,
294     IDC_CURNORMAL,
295     IDC_CURAPPLIC,
296     IDC_COMPOSEKEY,
297     IDC_CTRLALTKEYS,
298     IDC_TELNETKEY,
299     keyboardpanelend,
300
301     terminalpanelstart,
302     IDC_TITLE_TERMINAL,
303     IDC_BOX_TERMINAL1,
304     IDC_BOX_TERMINAL2,
305     IDC_WRAPMODE,
306     IDC_DECOM,
307     IDC_LFHASCR,
308     IDC_BCE,
309     IDC_BLINKTEXT,
310     IDC_ANSWERBACK,
311     IDC_ANSWEREDIT,
312     IDC_ECHOSTATIC,
313     IDC_ECHOBACKEND,
314     IDC_ECHOYES,
315     IDC_ECHONO,
316     IDC_EDITSTATIC,
317     IDC_EDITBACKEND,
318     IDC_EDITYES,
319     IDC_EDITNO,
320     terminalpanelend,
321
322     bellpanelstart,
323     IDC_TITLE_BELL,
324     IDC_BOX_BELL1,
325     IDC_BOX_BELL2,
326     IDC_BELLSTATIC,
327     IDC_BELL_DISABLED,
328     IDC_BELL_DEFAULT,
329     IDC_BELL_WAVEFILE,
330     IDC_BELL_VISUAL,
331     IDC_BELL_WAVESTATIC,
332     IDC_BELL_WAVEEDIT,
333     IDC_BELL_WAVEBROWSE,
334     IDC_B_IND_STATIC,
335     IDC_B_IND_DISABLED,
336     IDC_B_IND_FLASH,
337     IDC_B_IND_STEADY,
338     IDC_BELLOVL,
339     IDC_BELLOVLNSTATIC,
340     IDC_BELLOVLN,
341     IDC_BELLOVLTSTATIC,
342     IDC_BELLOVLT,
343     IDC_BELLOVLEXPLAIN,
344     IDC_BELLOVLSSTATIC,
345     IDC_BELLOVLS,
346     bellpanelend,
347
348     windowpanelstart,
349     IDC_TITLE_WINDOW,
350     IDC_BOX_WINDOW1,
351     IDC_BOX_WINDOW2,
352     IDC_BOX_WINDOW3,
353     IDC_ROWSSTATIC,
354     IDC_ROWSEDIT,
355     IDC_COLSSTATIC,
356     IDC_COLSEDIT,
357     IDC_RESIZESTATIC,
358     IDC_RESIZETERM,
359     IDC_RESIZEFONT,
360     IDC_RESIZENONE,
361     IDC_RESIZEEITHER,
362     IDC_SCROLLBAR,
363     IDC_SCROLLBARFULLSCREEN,
364     IDC_SAVESTATIC,
365     IDC_SAVEEDIT,
366     IDC_SCROLLKEY,
367     IDC_SCROLLDISP,
368     windowpanelend,
369
370     behaviourpanelstart,
371     IDC_TITLE_BEHAVIOUR,
372     IDC_BOX_BEHAVIOUR1,
373     IDC_CLOSEWARN,
374     IDC_ALTF4,
375     IDC_ALTSPACE,
376     IDC_ALTONLY,
377     IDC_ALWAYSONTOP,
378     IDC_FULLSCREENONALTENTER,
379     behaviourpanelend,
380
381     appearancepanelstart,
382     IDC_TITLE_APPEARANCE,
383     IDC_BOX_APPEARANCE1,
384     IDC_BOX_APPEARANCE2,
385     IDC_BOX_APPEARANCE3,
386     IDC_BOX_APPEARANCE4,
387     IDC_BOX_APPEARANCE5,
388     IDC_CURSORSTATIC,
389     IDC_CURBLOCK,
390     IDC_CURUNDER,
391     IDC_CURVERT,
392     IDC_BLINKCUR,
393     IDC_FONTSTATIC,
394     IDC_CHOOSEFONT,
395     IDC_WINTITLE,
396     IDC_WINEDIT,
397     IDC_WINNAME,
398     IDC_HIDEMOUSE,
399     IDC_SUNKENEDGE,
400     IDC_WINBSTATIC,
401     IDC_WINBEDIT,
402     appearancepanelend,
403
404     connectionpanelstart,
405     IDC_TITLE_CONNECTION,
406     IDC_BOX_CONNECTION1,
407     IDC_BOX_CONNECTION2,
408     IDC_TTSTATIC,
409     IDC_TTEDIT,
410     IDC_LOGSTATIC,
411     IDC_LOGEDIT,
412     IDC_PINGSTATIC,
413     IDC_PINGEDIT,
414     connectionpanelend,
415
416     telnetpanelstart,
417     IDC_TITLE_TELNET,
418     IDC_BOX_TELNET1,
419     IDC_BOX_TELNET2,
420     IDC_TSSTATIC,
421     IDC_TSEDIT,
422     IDC_ENVSTATIC,
423     IDC_VARSTATIC,
424     IDC_VAREDIT,
425     IDC_VALSTATIC,
426     IDC_VALEDIT,
427     IDC_ENVLIST,
428     IDC_ENVADD,
429     IDC_ENVREMOVE,
430     IDC_EMSTATIC,
431     IDC_EMBSD,
432     IDC_EMRFC,
433     IDC_ACTSTATIC,
434     IDC_TPASSIVE,
435     IDC_TACTIVE,
436     telnetpanelend,
437
438     rloginpanelstart,
439     IDC_TITLE_RLOGIN,
440     IDC_BOX_RLOGIN1,
441     IDC_BOX_RLOGIN2,
442     IDC_R_TSSTATIC,
443     IDC_R_TSEDIT,
444     IDC_RLLUSERSTATIC,
445     IDC_RLLUSEREDIT,
446     rloginpanelend,
447
448     sshpanelstart,
449     IDC_TITLE_SSH,
450     IDC_BOX_SSH1,
451     IDC_BOX_SSH2,
452     IDC_BOX_SSH3,
453     IDC_NOPTY,
454     IDC_BOX_SSHCIPHER,
455     IDC_CIPHERSTATIC2,
456     IDC_CIPHERLIST,
457     IDC_CIPHERUP,
458     IDC_CIPHERDN,
459     IDC_BUGGYMAC,
460     IDC_SSHPROTSTATIC,
461     IDC_SSHPROT1,
462     IDC_SSHPROT2,
463     IDC_CMDSTATIC,
464     IDC_CMDEDIT,
465     IDC_COMPRESS,
466     sshpanelend,
467
468     sshauthpanelstart,
469     IDC_TITLE_SSHAUTH,
470     IDC_BOX_SSHAUTH1,
471     IDC_BOX_SSHAUTH2,
472     IDC_PKSTATIC,
473     IDC_PKEDIT,
474     IDC_PKBUTTON,
475     IDC_AGENTFWD,
476     IDC_AUTHTIS,
477     IDC_AUTHKI,
478     sshauthpanelend,
479
480     selectionpanelstart,
481     IDC_TITLE_SELECTION,
482     IDC_BOX_SELECTION1,
483     IDC_BOX_SELECTION2,
484     IDC_BOX_SELECTION3,
485     IDC_MBSTATIC,
486     IDC_MBWINDOWS,
487     IDC_MBXTERM,
488     IDC_MOUSEOVERRIDE,
489     IDC_SELTYPESTATIC,
490     IDC_SELTYPELEX,
491     IDC_SELTYPERECT,
492     IDC_CCSTATIC,
493     IDC_CCLIST,
494     IDC_CCSET,
495     IDC_CCSTATIC2,
496     IDC_CCEDIT,
497     IDC_RAWCNP,
498     IDC_RTFPASTE,
499     selectionpanelend,
500
501     colourspanelstart,
502     IDC_TITLE_COLOURS,
503     IDC_BOX_COLOURS1,
504     IDC_BOX_COLOURS2,
505     IDC_BOLDCOLOUR,
506     IDC_PALETTE,
507     IDC_COLOURSTATIC,
508     IDC_COLOURLIST,
509     IDC_RSTATIC,
510     IDC_GSTATIC,
511     IDC_BSTATIC,
512     IDC_RVALUE,
513     IDC_GVALUE,
514     IDC_BVALUE,
515     IDC_CHANGE,
516     colourspanelend,
517
518     translationpanelstart,
519     IDC_TITLE_TRANSLATION,
520     IDC_BOX_TRANSLATION1,
521     IDC_BOX_TRANSLATION2,
522     IDC_BOX_TRANSLATION3,
523     IDC_CODEPAGESTATIC,
524     IDC_CODEPAGE,
525     IDC_CAPSLOCKCYR,
526     IDC_VTSTATIC,
527     IDC_VTXWINDOWS,
528     IDC_VTOEMANSI,
529     IDC_VTOEMONLY,
530     IDC_VTPOORMAN,
531     IDC_VTUNICODE,
532     translationpanelend,
533
534     tunnelspanelstart,
535     IDC_TITLE_TUNNELS,
536     IDC_BOX_TUNNELS1,
537     IDC_BOX_TUNNELS2,
538     IDC_X11_FORWARD,
539     IDC_X11_DISPSTATIC,
540     IDC_X11_DISPLAY,
541     IDC_LPORT_ALL,
542     IDC_PFWDSTATIC,
543     IDC_PFWDSTATIC2,
544     IDC_PFWDREMOVE,
545     IDC_PFWDLIST,
546     IDC_PFWDADD,
547     IDC_SPORTSTATIC,
548     IDC_SPORTEDIT,
549     IDC_DPORTSTATIC,
550     IDC_DPORTEDIT,
551     IDC_PFWDLOCAL,
552     IDC_PFWDREMOTE,
553
554     tunnelspanelend,
555
556     controlendvalue
557 };
558
559 static const char *const colours[] = {
560     "Default Foreground", "Default Bold Foreground",
561     "Default Background", "Default Bold Background",
562     "Cursor Text", "Cursor Colour",
563     "ANSI Black", "ANSI Black Bold",
564     "ANSI Red", "ANSI Red Bold",
565     "ANSI Green", "ANSI Green Bold",
566     "ANSI Yellow", "ANSI Yellow Bold",
567     "ANSI Blue", "ANSI Blue Bold",
568     "ANSI Magenta", "ANSI Magenta Bold",
569     "ANSI Cyan", "ANSI Cyan Bold",
570     "ANSI White", "ANSI White Bold"
571 };
572 static const int permcolour[] = {
573     TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
574     TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
575     TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
576 };
577
578 static void fmtfont(char *buf)
579 {
580     sprintf(buf, "Font: %s, ", cfg.font);
581     if (cfg.fontisbold)
582         strcat(buf, "bold, ");
583     if (cfg.fontheight == 0)
584         strcat(buf, "default height");
585     else
586         sprintf(buf + strlen(buf), "%d-point",
587                 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight));
588 }
589
590 /* 2nd arg: NZ => don't redraw session list (use when loading
591  * a new session) */
592 static void init_dlg_ctrls(HWND hwnd, int keepsess)
593 {
594     int i;
595     char fontstatic[256];
596
597     SetDlgItemText(hwnd, IDC_HOST, cfg.host);
598     SetDlgItemText(hwnd, IDC_SESSEDIT, savedsession);
599     if (!keepsess) {
600         int i, n;
601         n = SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_GETCOUNT, 0, 0);
602         for (i = n; i-- > 0;)
603             SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_DELETESTRING, i, 0);
604         for (i = 0; i < nsessions; i++)
605             SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_ADDSTRING,
606                                0, (LPARAM) (sessions[i]));
607     }
608     SetDlgItemInt(hwnd, IDC_PORT, cfg.port, FALSE);
609     CheckRadioButton(hwnd, IDC_PROTRAW, IDC_PROTSSH,
610                      cfg.protocol == PROT_SSH ? IDC_PROTSSH :
611                      cfg.protocol == PROT_TELNET ? IDC_PROTTELNET :
612                      cfg.protocol ==
613                      PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW);
614     SetDlgItemInt(hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
615
616     CheckRadioButton(hwnd, IDC_DEL008, IDC_DEL127,
617                      cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
618     CheckRadioButton(hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
619                      cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
620     CheckRadioButton(hwnd, IDC_FUNCTILDE, IDC_FUNCSCO,
621                      cfg.funky_type == 0 ? IDC_FUNCTILDE :
622                      cfg.funky_type == 1 ? IDC_FUNCLINUX :
623                      cfg.funky_type == 2 ? IDC_FUNCXTERM :
624                      cfg.funky_type == 3 ? IDC_FUNCVT400 :
625                      cfg.funky_type == 4 ? IDC_FUNCVT100P :
626                      cfg.funky_type == 5 ? IDC_FUNCSCO : IDC_FUNCTILDE);
627     CheckDlgButton(hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
628     CheckDlgButton(hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
629     CheckRadioButton(hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
630                      cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
631     CheckRadioButton(hwnd, IDC_KPNORMAL, IDC_KPNH,
632                      cfg.nethack_keypad ? IDC_KPNH :
633                      cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
634     CheckDlgButton(hwnd, IDC_ALTF4, cfg.alt_f4);
635     CheckDlgButton(hwnd, IDC_ALTSPACE, cfg.alt_space);
636     CheckDlgButton(hwnd, IDC_ALTONLY, cfg.alt_only);
637     CheckDlgButton(hwnd, IDC_COMPOSEKEY, cfg.compose_key);
638     CheckDlgButton(hwnd, IDC_CTRLALTKEYS, cfg.ctrlaltkeys);
639     CheckDlgButton(hwnd, IDC_TELNETKEY, cfg.telnet_keyboard);
640     CheckRadioButton(hwnd, IDC_ECHOBACKEND, IDC_ECHONO,
641                      cfg.localecho == LD_BACKEND ? IDC_ECHOBACKEND :
642                      cfg.localecho == LD_YES ? IDC_ECHOYES : IDC_ECHONO);
643     CheckRadioButton(hwnd, IDC_EDITBACKEND, IDC_EDITNO,
644                      cfg.localedit == LD_BACKEND ? IDC_EDITBACKEND :
645                      cfg.localedit == LD_YES ? IDC_EDITYES : IDC_EDITNO);
646     SetDlgItemText(hwnd, IDC_ANSWEREDIT, cfg.answerback);
647     CheckDlgButton(hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
648     CheckDlgButton(hwnd, IDC_FULLSCREENONALTENTER, cfg.fullscreenonaltenter);
649     CheckDlgButton(hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
650     CheckDlgButton(hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
651
652     CheckDlgButton(hwnd, IDC_WRAPMODE, cfg.wrap_mode);
653     CheckDlgButton(hwnd, IDC_DECOM, cfg.dec_om);
654     CheckDlgButton(hwnd, IDC_LFHASCR, cfg.lfhascr);
655     SetDlgItemInt(hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
656     SetDlgItemInt(hwnd, IDC_COLSEDIT, cfg.width, FALSE);
657     SetDlgItemInt(hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
658     fmtfont(fontstatic);
659     SetDlgItemText(hwnd, IDC_FONTSTATIC, fontstatic);
660     CheckRadioButton(hwnd, IDC_BELL_DISABLED, IDC_BELL_VISUAL,
661                      cfg.beep == BELL_DISABLED ? IDC_BELL_DISABLED :
662                      cfg.beep == BELL_DEFAULT ? IDC_BELL_DEFAULT :
663                      cfg.beep == BELL_WAVEFILE ? IDC_BELL_WAVEFILE :
664                      cfg.beep ==
665                      BELL_VISUAL ? IDC_BELL_VISUAL : IDC_BELL_DEFAULT);
666     CheckRadioButton(hwnd, IDC_B_IND_DISABLED, IDC_B_IND_STEADY,
667                      cfg.beep_ind ==
668                      B_IND_DISABLED ? IDC_B_IND_DISABLED : cfg.beep_ind ==
669                      B_IND_FLASH ? IDC_B_IND_FLASH : cfg.beep_ind ==
670                      B_IND_STEADY ? IDC_B_IND_STEADY : IDC_B_IND_DISABLED);
671     SetDlgItemText(hwnd, IDC_BELL_WAVEEDIT, cfg.bell_wavefile);
672     CheckDlgButton(hwnd, IDC_BELLOVL, cfg.bellovl);
673     SetDlgItemInt(hwnd, IDC_BELLOVLN, cfg.bellovl_n, FALSE);
674     MySetDlgItemFlt(hwnd, IDC_BELLOVLT, cfg.bellovl_t / 1000.0);
675     MySetDlgItemFlt(hwnd, IDC_BELLOVLS, cfg.bellovl_s / 1000.0);
676
677     CheckDlgButton(hwnd, IDC_BCE, cfg.bce);
678     CheckDlgButton(hwnd, IDC_BLINKTEXT, cfg.blinktext);
679
680     SetDlgItemText(hwnd, IDC_WINEDIT, cfg.wintitle);
681     CheckDlgButton(hwnd, IDC_WINNAME, cfg.win_name_always);
682     CheckDlgButton(hwnd, IDC_HIDEMOUSE, cfg.hide_mouseptr);
683     CheckDlgButton(hwnd, IDC_SUNKENEDGE, cfg.sunken_edge);
684     SetDlgItemInt(hwnd, IDC_WINBEDIT, cfg.window_border, FALSE);
685     CheckRadioButton(hwnd, IDC_CURBLOCK, IDC_CURVERT,
686                      cfg.cursor_type == 0 ? IDC_CURBLOCK :
687                      cfg.cursor_type == 1 ? IDC_CURUNDER : IDC_CURVERT);
688     CheckDlgButton(hwnd, IDC_BLINKCUR, cfg.blink_cur);
689     CheckDlgButton(hwnd, IDC_SCROLLBAR, cfg.scrollbar);
690     CheckDlgButton(hwnd, IDC_SCROLLBARFULLSCREEN, cfg.scrollbar_in_fullscreen);
691     CheckRadioButton(hwnd, IDC_RESIZETERM, IDC_RESIZEEITHER,
692                      cfg.resize_action == RESIZE_TERM ? IDC_RESIZETERM :
693                      cfg.resize_action == RESIZE_FONT ? IDC_RESIZEFONT :
694                      cfg.resize_action == RESIZE_EITHER ? IDC_RESIZEEITHER :
695                      IDC_RESIZENONE);
696     CheckRadioButton(hwnd, IDC_COEALWAYS, IDC_COENORMAL,
697                      cfg.close_on_exit == COE_NORMAL ? IDC_COENORMAL :
698                      cfg.close_on_exit ==
699                      COE_NEVER ? IDC_COENEVER : IDC_COEALWAYS);
700     CheckDlgButton(hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
701
702     SetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype);
703     SetDlgItemText(hwnd, IDC_TSEDIT, cfg.termspeed);
704     SetDlgItemText(hwnd, IDC_R_TSEDIT, cfg.termspeed);
705     SetDlgItemText(hwnd, IDC_RLLUSEREDIT, cfg.localusername);
706     SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
707     SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
708     CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
709                      cfg.logtype == 0 ? IDC_LSTATOFF :
710                      cfg.logtype == 1 ? IDC_LSTATASCII : IDC_LSTATRAW);
711     CheckRadioButton(hwnd, IDC_LSTATXOVR, IDC_LSTATXASK,
712                      cfg.logxfovr == LGXF_OVR ? IDC_LSTATXOVR :
713                      cfg.logxfovr == LGXF_ASK ? IDC_LSTATXASK :
714                      IDC_LSTATXAPN);
715     {
716         char *p = cfg.environmt;
717         SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_RESETCONTENT, 0, 0);
718         while (*p) {
719             SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
720                                (LPARAM) p);
721             p += strlen(p) + 1;
722         }
723         p = cfg.portfwd;
724         while (*p) {
725             SendDlgItemMessage(hwnd, IDC_PFWDLIST, LB_ADDSTRING, 0,
726                                (LPARAM) p);
727             p += strlen(p) + 1;
728         }
729     }
730     CheckRadioButton(hwnd, IDC_EMBSD, IDC_EMRFC,
731                      cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
732     CheckRadioButton(hwnd, IDC_TPASSIVE, IDC_TACTIVE,
733                      cfg.passive_telnet ? IDC_TPASSIVE : IDC_TACTIVE);
734
735     SetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype);
736     SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
737     CheckDlgButton(hwnd, IDC_NOPTY, cfg.nopty);
738     CheckDlgButton(hwnd, IDC_COMPRESS, cfg.compression);
739     CheckDlgButton(hwnd, IDC_BUGGYMAC, cfg.buggymac);
740     CheckDlgButton(hwnd, IDC_AGENTFWD, cfg.agentfwd);
741     CheckRadioButton(hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
742                      cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
743     CheckDlgButton(hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
744     CheckDlgButton(hwnd, IDC_AUTHKI, cfg.try_ki_auth);
745     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
746     SetDlgItemText(hwnd, IDC_CMDEDIT, cfg.remote_cmd);
747
748     {
749         int i;
750         static const struct { char *s; int c; } ciphers[] = {
751             { "3DES",                   CIPHER_3DES },
752             { "Blowfish",               CIPHER_BLOWFISH },
753             { "DES",                    CIPHER_DES },
754             { "AES (SSH 2 only)",       CIPHER_AES },
755             { "-- warn below here --",  CIPHER_WARN }
756         };
757
758         /* Set up the "selected ciphers" box. */
759         /* (cipherlist assumed to contain all ciphers) */
760         SendDlgItemMessage(hwnd, IDC_CIPHERLIST, LB_RESETCONTENT, 0, 0);
761         for (i = 0; i < CIPHER_MAX; i++) {
762             int c = cfg.ssh_cipherlist[i];
763             int j, pos;
764             char *cstr = NULL;
765             for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) {
766                 if (ciphers[j].c == c) {
767                     cstr = ciphers[j].s;
768                     break;
769                 }
770             }
771             pos = SendDlgItemMessage(hwnd, IDC_CIPHERLIST, LB_ADDSTRING,
772                                      0, (LPARAM) cstr);
773             SendDlgItemMessage(hwnd, IDC_CIPHERLIST, LB_SETITEMDATA,
774                                pos, (LPARAM) c);
775         }
776
777     }
778
779     CheckRadioButton(hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
780                      cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
781     CheckRadioButton(hwnd, IDC_SELTYPELEX, IDC_SELTYPERECT,
782                      cfg.rect_select == 0 ? IDC_SELTYPELEX : IDC_SELTYPERECT);
783     CheckDlgButton(hwnd, IDC_MOUSEOVERRIDE, cfg.mouse_override);
784     CheckDlgButton(hwnd, IDC_RAWCNP, cfg.rawcnp);
785     CheckDlgButton(hwnd, IDC_RTFPASTE, cfg.rtf_paste);
786     {
787         static int tabs[4] = { 25, 61, 96, 128 };
788         SendDlgItemMessage(hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
789                            (LPARAM) tabs);
790     }
791     for (i = 0; i < 128; i++) {
792         char str[100];
793         sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
794                 (i >= 0x21 && i != 0x7F) ? i : ' ', cfg.wordness[i]);
795         SendDlgItemMessage(hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
796                            (LPARAM) str);
797     }
798
799     CheckDlgButton(hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
800     CheckDlgButton(hwnd, IDC_PALETTE, cfg.try_palette);
801     {
802         int i, n;
803         n = SendDlgItemMessage(hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
804         for (i = n; i-- > 0;)
805             SendDlgItemMessage(hwnd, IDC_COLOURLIST,
806                                LB_DELETESTRING, i, 0);
807         for (i = 0; i < 22; i++)
808             if (cfg.bold_colour || permcolour[i])
809                 SendDlgItemMessage(hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
810                                    (LPARAM) colours[i]);
811     }
812     SendDlgItemMessage(hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
813     SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
814     SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
815     SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
816
817     {
818         int i;
819         char *cp;
820         strcpy(cfg.line_codepage, cp_name(decode_codepage(cfg.line_codepage)));
821         SendDlgItemMessage(hwnd, IDC_CODEPAGE, CB_RESETCONTENT, 0, 0);
822         CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
823         for (i = 0; (cp = cp_enumerate(i)) != NULL; i++) {
824             SendDlgItemMessage(hwnd, IDC_CODEPAGE, CB_ADDSTRING,
825                                0, (LPARAM) cp);
826         }
827         SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
828     }
829     
830     CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTUNICODE,
831                      cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
832                      cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
833                      cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
834                      cfg.vtmode == VT_UNICODE ? IDC_VTUNICODE :
835                      IDC_VTPOORMAN);
836
837     CheckDlgButton(hwnd, IDC_X11_FORWARD, cfg.x11_forward);
838     SetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display);
839
840     CheckDlgButton(hwnd, IDC_LPORT_ALL, cfg.lport_acceptall);
841     CheckRadioButton(hwnd, IDC_PFWDLOCAL, IDC_PFWDREMOTE, IDC_PFWDLOCAL);
842 }
843
844 struct treeview_faff {
845     HWND treeview;
846     HTREEITEM lastat[4];
847 };
848
849 static HTREEITEM treeview_insert(struct treeview_faff *faff,
850                                  int level, char *text)
851 {
852     TVINSERTSTRUCT ins;
853     int i;
854     HTREEITEM newitem;
855     ins.hParent = (level > 0 ? faff->lastat[level - 1] : TVI_ROOT);
856     ins.hInsertAfter = faff->lastat[level];
857 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
858 #define INSITEM DUMMYUNIONNAME.item
859 #else
860 #define INSITEM item
861 #endif
862     ins.INSITEM.mask = TVIF_TEXT;
863     ins.INSITEM.pszText = text;
864     newitem = TreeView_InsertItem(faff->treeview, &ins);
865     if (level > 0)
866         TreeView_Expand(faff->treeview, faff->lastat[level - 1],
867                         TVE_EXPAND);
868     faff->lastat[level] = newitem;
869     for (i = level + 1; i < 4; i++)
870         faff->lastat[i] = NULL;
871     return newitem;
872 }
873
874 /*
875  * Create the panelfuls of controls in the configuration box.
876  */
877 static void create_controls(HWND hwnd, int dlgtype, int panel)
878 {
879     if (panel == sessionpanelstart) {
880         /* The Session panel. Accelerators used: [acgo] nprtih elsd w */
881         struct ctlpos cp;
882         ctlposinit(&cp, hwnd, 80, 3, 13);
883         bartitle(&cp, "Basic options for your PuTTY session",
884                  IDC_TITLE_SESSION);
885         if (dlgtype == 0) {
886             beginbox(&cp, "Specify your connection by host name or IP address",
887                      IDC_BOX_SESSION1);
888             multiedit(&cp,
889                       "Host &Name (or IP address)",
890                       IDC_HOSTSTATIC, IDC_HOST, 75,
891                       "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
892             if (backends[3].backend == NULL) {
893                 /* this is PuTTYtel, so only three protocols available */
894                 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
895                           "&Raw", IDC_PROTRAW,
896                           "&Telnet", IDC_PROTTELNET,
897                           "Rlog&in", IDC_PROTRLOGIN, NULL);
898             } else {
899                 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
900                           "&Raw", IDC_PROTRAW,
901                           "&Telnet", IDC_PROTTELNET,
902                           "Rlog&in", IDC_PROTRLOGIN,
903 #ifdef FWHACK
904                           "SS&H/hack",
905 #else
906                           "SS&H",
907 #endif
908                           IDC_PROTSSH, NULL);
909             }
910             endbox(&cp);
911             beginbox(&cp, "Load, save or delete a stored session",
912                      IDC_BOX_SESSION2);
913             sesssaver(&cp, "Sav&ed Sessions",
914                       IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
915                       "&Load", IDC_SESSLOAD,
916                       "&Save", IDC_SESSSAVE, "&Delete", IDC_SESSDEL, NULL);
917             endbox(&cp);
918         }
919         beginbox(&cp, NULL, IDC_BOX_SESSION3);
920         radioline(&cp, "Close &window on exit:", IDC_CLOSEEXIT, 4,
921                   "Always", IDC_COEALWAYS,
922                   "Never", IDC_COENEVER,
923                   "Only on clean exit", IDC_COENORMAL, NULL);
924         endbox(&cp);
925     }
926
927     if (panel == loggingpanelstart) {
928         /* The Logging panel. Accelerators used: [acgo] tplfwe */
929         struct ctlpos cp;
930         ctlposinit(&cp, hwnd, 80, 3, 13);
931         bartitle(&cp, "Options controlling session logging",
932                  IDC_TITLE_LOGGING);
933         beginbox(&cp, NULL, IDC_BOX_LOGGING1);
934         radiobig(&cp,
935                  "Session logging:", IDC_LSTATSTATIC,
936                  "Logging &turned off completely", IDC_LSTATOFF,
937                  "Log &printable output only", IDC_LSTATASCII,
938                  "&Log all session output", IDC_LSTATRAW, NULL);
939         editbutton(&cp, "Log &file name:",
940                    IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
941                    IDC_LGFBUTTON);
942         statictext(&cp, "(Log file name can contain &&Y, &&M, &&D for date,"
943                    " &&T for time, and &&H for host name)", 2, IDC_LGFEXPLAIN);
944         radiobig(&cp,
945                  "What to do if the log file already &exists:",
946                  IDC_LSTATXIST, "Always overwrite it", IDC_LSTATXOVR,
947                  "Always append to the end of it", IDC_LSTATXAPN,
948                  "Ask the user every time", IDC_LSTATXASK, NULL);
949         endbox(&cp);
950     }
951
952     if (panel == terminalpanelstart) {
953         /* The Terminal panel. Accelerators used: [acgo] wdlen hts */
954         struct ctlpos cp;
955         ctlposinit(&cp, hwnd, 80, 3, 13);
956         bartitle(&cp, "Options controlling the terminal emulation",
957                  IDC_TITLE_TERMINAL);
958         beginbox(&cp, "Set various terminal options", IDC_BOX_TERMINAL1);
959         checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
960         checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
961         checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
962         checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
963         checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
964         multiedit(&cp,
965                   "An&swerback to ^E:", IDC_ANSWERBACK,
966                   IDC_ANSWEREDIT, 100, NULL);
967         endbox(&cp);
968
969         beginbox(&cp, "Line discipline options", IDC_BOX_TERMINAL2);
970         radioline(&cp, "Local ec&ho:", IDC_ECHOSTATIC, 3,
971                   "Auto", IDC_ECHOBACKEND,
972                   "Force on", IDC_ECHOYES, "Force off", IDC_ECHONO, NULL);
973         radioline(&cp, "Local line edi&ting:", IDC_EDITSTATIC, 3,
974                   "Auto", IDC_EDITBACKEND,
975                   "Force on", IDC_EDITYES, "Force off", IDC_EDITNO, NULL);
976         endbox(&cp);
977     }
978
979     if (panel == bellpanelstart) {
980         /* The Bell panel. Accelerators used: [acgo] bdsm wit */
981         struct ctlpos cp;
982         ctlposinit(&cp, hwnd, 80, 3, 13);
983         bartitle(&cp, "Options controlling the terminal bell",
984                  IDC_TITLE_BELL);
985         beginbox(&cp, "Set the style of bell", IDC_BOX_BELL1);
986         radiobig(&cp,
987                  "Action to happen when a &bell occurs:", IDC_BELLSTATIC,
988                  "None (bell disabled)", IDC_BELL_DISABLED,
989                  "Play Windows Default Sound", IDC_BELL_DEFAULT,
990                  "Play a custom sound file", IDC_BELL_WAVEFILE,
991                  "Visual bell (flash window)", IDC_BELL_VISUAL, NULL);
992         editbutton(&cp, "Custom sound file to play as a bell:",
993                    IDC_BELL_WAVESTATIC, IDC_BELL_WAVEEDIT,
994                    "Bro&wse...", IDC_BELL_WAVEBROWSE);
995         radioline(&cp, "Taskbar/caption &indication on bell:",
996                   IDC_B_IND_STATIC, 3, "Disabled", IDC_B_IND_DISABLED,
997                   "Flashing", IDC_B_IND_FLASH, "Steady", IDC_B_IND_STEADY,
998                   NULL);
999         endbox(&cp);
1000         beginbox(&cp, "Control the bell overload behaviour",
1001                  IDC_BOX_BELL2);
1002         checkbox(&cp, "Bell is temporarily &disabled when over-used",
1003                  IDC_BELLOVL);
1004         staticedit(&cp, "Over-use means this &many bells...",
1005                    IDC_BELLOVLNSTATIC, IDC_BELLOVLN, 20);
1006         staticedit(&cp, "... in &this many seconds",
1007                    IDC_BELLOVLTSTATIC, IDC_BELLOVLT, 20);
1008         statictext(&cp,
1009                    "The bell is re-enabled after a few seconds of silence.",
1010                    1, IDC_BELLOVLEXPLAIN);
1011         staticedit(&cp, "Seconds of &silence required", IDC_BELLOVLSSTATIC,
1012                    IDC_BELLOVLS, 20);
1013         endbox(&cp);
1014     }
1015
1016     if (panel == keyboardpanelstart) {
1017         /* The Keyboard panel. Accelerators used: [acgo] bhf ruyntd */
1018         struct ctlpos cp;
1019         ctlposinit(&cp, hwnd, 80, 3, 13);
1020         bartitle(&cp, "Options controlling the effects of keys",
1021                  IDC_TITLE_KEYBOARD);
1022         beginbox(&cp, "Change the sequences sent by:", IDC_BOX_KEYBOARD1);
1023         radioline(&cp, "The &Backspace key", IDC_DELSTATIC, 2,
1024                   "Control-H", IDC_DEL008,
1025                   "Control-? (127)", IDC_DEL127, NULL);
1026         radioline(&cp, "The &Home and End keys", IDC_HOMESTATIC, 2,
1027                   "Standard", IDC_HOMETILDE, "rxvt", IDC_HOMERXVT, NULL);
1028         radioline(&cp, "The &Function keys and keypad", IDC_FUNCSTATIC, 3,
1029                   "ESC[n~", IDC_FUNCTILDE,
1030                   "Linux", IDC_FUNCLINUX,
1031                   "Xterm R6", IDC_FUNCXTERM,
1032                   "VT400", IDC_FUNCVT400,
1033                   "VT100+", IDC_FUNCVT100P, "SCO", IDC_FUNCSCO, NULL);
1034         endbox(&cp);
1035         beginbox(&cp, "Application keypad settings:", IDC_BOX_KEYBOARD2);
1036         checkbox(&cp,
1037                  "Application c&ursor keys totally disabled",
1038                  IDC_NOAPPLICC);
1039         radioline(&cp, "Initial state of cu&rsor keys:", IDC_CURSTATIC, 2,
1040                   "Normal", IDC_CURNORMAL,
1041                   "Application", IDC_CURAPPLIC, NULL);
1042         checkbox(&cp,
1043                  "Application ke&ypad keys totally disabled",
1044                  IDC_NOAPPLICK);
1045         radioline(&cp, "Initial state of &numeric keypad:", IDC_KPSTATIC,
1046                   3, "Normal", IDC_KPNORMAL, "Application", IDC_KPAPPLIC,
1047                   "NetHack", IDC_KPNH, NULL);
1048         endbox(&cp);
1049         beginbox(&cp, "Enable extra keyboard features:",
1050                  IDC_BOX_KEYBOARD3);
1051         checkbox(&cp, "AltGr ac&ts as Compose key", IDC_COMPOSEKEY);
1052         checkbox(&cp, "Control-Alt is &different from AltGr",
1053                  IDC_CTRLALTKEYS);
1054         endbox(&cp);
1055     }
1056
1057     if (panel == windowpanelstart) {
1058         /* The Window panel. Accelerators used: [acgo] rmz sdikp */
1059         struct ctlpos cp;
1060         ctlposinit(&cp, hwnd, 80, 3, 13);
1061         bartitle(&cp, "Options controlling PuTTY's window",
1062                  IDC_TITLE_WINDOW);
1063         beginbox(&cp, "Set the size of the window", IDC_BOX_WINDOW1);
1064         multiedit(&cp,
1065                   "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
1066                   "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50, NULL);
1067         radiobig(&cp, "When window is resi&zed:", IDC_RESIZESTATIC,
1068                  "Change the number of rows and columns", IDC_RESIZETERM,
1069                  "Change the size of the font", IDC_RESIZEFONT,
1070                  "Change font size only when maximised", IDC_RESIZEEITHER,
1071                  "Forbid resizing completely", IDC_RESIZENONE, NULL);
1072         endbox(&cp);
1073         beginbox(&cp, "Control the scrollback in the window",
1074                  IDC_BOX_WINDOW2);
1075         staticedit(&cp, "Lines of &scrollback",
1076                    IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
1077         checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
1078         checkbox(&cp, "D&isplay scrollbar in full screen mode", IDC_SCROLLBARFULLSCREEN);
1079         checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1080         checkbox(&cp, "Reset scrollback on dis&play activity",
1081                  IDC_SCROLLDISP);
1082         endbox(&cp);
1083     }
1084
1085     if (panel == appearancepanelstart) {
1086         /* The Appearance panel. Accelerators used: [acgo] luvb h ti p s */
1087         struct ctlpos cp;
1088         ctlposinit(&cp, hwnd, 80, 3, 13);
1089         bartitle(&cp, "Configure the appearance of PuTTY's window",
1090                  IDC_TITLE_APPEARANCE);
1091         beginbox(&cp, "Adjust the use of the cursor", IDC_BOX_APPEARANCE1);
1092         radioline(&cp, "Cursor appearance:", IDC_CURSORSTATIC, 3,
1093                   "B&lock", IDC_CURBLOCK,
1094                   "&Underline", IDC_CURUNDER,
1095                   "&Vertical line", IDC_CURVERT, NULL);
1096         checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
1097         endbox(&cp);
1098         beginbox(&cp, "Set the font used in the terminal window",
1099                  IDC_BOX_APPEARANCE2);
1100         staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1101         endbox(&cp);
1102         beginbox(&cp, "Adjust the use of the window title",
1103                  IDC_BOX_APPEARANCE3);
1104         multiedit(&cp,
1105                   "Window &title:", IDC_WINTITLE, IDC_WINEDIT, 100, NULL);
1106         checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1107         endbox(&cp);
1108         beginbox(&cp, "Adjust the use of the mouse pointer",
1109                  IDC_BOX_APPEARANCE4);
1110         checkbox(&cp, "Hide mouse &pointer when typing in window",
1111                  IDC_HIDEMOUSE);
1112         endbox(&cp);
1113         beginbox(&cp, "Adjust the window border", IDC_BOX_APPEARANCE5);
1114         checkbox(&cp, "&Sunken-edge border (slightly thicker)",
1115                  IDC_SUNKENEDGE);
1116         staticedit(&cp, "Gap between text and window edge",
1117                    IDC_WINBSTATIC, IDC_WINBEDIT, 20);
1118         endbox(&cp);
1119     }
1120
1121     if (panel == behaviourpanelstart) {
1122         /* The Behaviour panel. Accelerators used: [acgo] w4yltf */
1123         struct ctlpos cp;
1124         ctlposinit(&cp, hwnd, 80, 3, 13);
1125         bartitle(&cp, "Configure the behaviour of PuTTY's window",
1126                  IDC_TITLE_WINDOW);
1127         beginbox(&cp, NULL, IDC_BOX_BEHAVIOUR1);
1128         checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
1129         checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
1130         checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
1131         checkbox(&cp, "System menu appears on A&LT alone", IDC_ALTONLY);
1132         checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
1133         checkbox(&cp, "&Full screen on Alt-Enter", IDC_FULLSCREENONALTENTER);
1134         endbox(&cp);
1135     }
1136
1137     if (panel == translationpanelstart) {
1138         /* The Translation panel. Accelerators used: [acgo] rxbepus */
1139         struct ctlpos cp;
1140         ctlposinit(&cp, hwnd, 80, 3, 13);
1141         bartitle(&cp, "Options controlling character set translation",
1142                  IDC_TITLE_TRANSLATION);
1143         beginbox(&cp, "Character set translation on received data",
1144                  IDC_BOX_TRANSLATION1);
1145         combobox(&cp, "&Received data assumed to be in which character set:",
1146                  IDC_CODEPAGESTATIC, IDC_CODEPAGE);
1147         endbox(&cp);
1148         beginbox(&cp, "Enable character set translation on input data",
1149                  IDC_BOX_TRANSLATION2);
1150         checkbox(&cp, "Cap&s Lock acts as Cyrillic switch",
1151                  IDC_CAPSLOCKCYR);
1152         endbox(&cp);
1153         beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
1154                  IDC_BOX_TRANSLATION3);
1155         radiobig(&cp,
1156                  "Handling of line drawing characters:", IDC_VTSTATIC,
1157                  "Font has &XWindows encoding", IDC_VTXWINDOWS,
1158                  "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
1159                  "Use font in O&EM mode only", IDC_VTOEMONLY,
1160                  "&Poor man's line drawing (" "+" ", " "-" " and " "|" ")",
1161                  IDC_VTPOORMAN, "&Unicode mode", IDC_VTUNICODE, NULL);
1162         endbox(&cp);
1163     }
1164
1165     if (panel == selectionpanelstart) {
1166         /* The Selection panel. Accelerators used: [acgo] df wxp hst nr */
1167         struct ctlpos cp;
1168         ctlposinit(&cp, hwnd, 80, 3, 13);
1169         bartitle(&cp, "Options controlling copy and paste",
1170                  IDC_TITLE_SELECTION);
1171         beginbox(&cp, "Translation of pasted characters",
1172                  IDC_BOX_SELECTION1);
1173         checkbox(&cp,
1174                  "&Don't translate line drawing chars into +, - and |",
1175                  IDC_RAWCNP);
1176         checkbox(&cp,
1177                  "Paste to clipboard in RT&F as well as plain text",
1178                  IDC_RTFPASTE);
1179         endbox(&cp);
1180         beginbox(&cp, "Control which mouse button does which thing",
1181                  IDC_BOX_SELECTION2);
1182         radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1183                  "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1184                  "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1185                  NULL);
1186         checkbox(&cp,
1187                  "Shift overrides a&pplication's use of mouse",
1188                  IDC_MOUSEOVERRIDE);
1189         radioline(&cp,
1190                   "Default selection mode (Alt+drag does the other one):",
1191                   IDC_SELTYPESTATIC, 2,
1192                   "&Normal", IDC_SELTYPELEX,
1193                   "&Rectangular block", IDC_SELTYPERECT, NULL);
1194         endbox(&cp);
1195         beginbox(&cp, "Control the select-one-word-at-a-time mode",
1196                  IDC_BOX_SELECTION3);
1197         charclass(&cp, "C&haracter classes:", IDC_CCSTATIC, IDC_CCLIST,
1198                   "&Set", IDC_CCSET, IDC_CCEDIT,
1199                   "&to class", IDC_CCSTATIC2);
1200         endbox(&cp);
1201     }
1202
1203     if (panel == colourspanelstart) {
1204         /* The Colours panel. Accelerators used: [acgo] blum */
1205         struct ctlpos cp;
1206         ctlposinit(&cp, hwnd, 80, 3, 13);
1207         bartitle(&cp, "Options controlling use of colours",
1208                  IDC_TITLE_COLOURS);
1209         beginbox(&cp, "General options for colour usage",
1210                  IDC_BOX_COLOURS1);
1211         checkbox(&cp, "&Bolded text is a different colour",
1212                  IDC_BOLDCOLOUR);
1213         checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1214         endbox(&cp);
1215         beginbox(&cp, "Adjust the precise colours PuTTY displays",
1216                  IDC_BOX_COLOURS2);
1217         colouredit(&cp, "Select a colo&ur and then click to modify it:",
1218                    IDC_COLOURSTATIC, IDC_COLOURLIST,
1219                    "&Modify...", IDC_CHANGE,
1220                    "Red:", IDC_RSTATIC, IDC_RVALUE,
1221                    "Green:", IDC_GSTATIC, IDC_GVALUE,
1222                    "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1223         endbox(&cp);
1224     }
1225
1226     if (panel == connectionpanelstart) {
1227         /* The Connection panel. Accelerators used: [acgo] tuk */
1228         struct ctlpos cp;
1229         ctlposinit(&cp, hwnd, 80, 3, 13);
1230         bartitle(&cp, "Options controlling the connection",
1231                  IDC_TITLE_CONNECTION);
1232         if (dlgtype == 0) {
1233             beginbox(&cp, "Data to send to the server",
1234                      IDC_BOX_CONNECTION1);
1235             staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC,
1236                        IDC_TTEDIT, 50);
1237             staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC,
1238                        IDC_LOGEDIT, 50);
1239             endbox(&cp);
1240         } else {
1241             beginbox(&cp, "Adjust telnet session.", IDC_BOX_CONNECTION1);
1242             checkbox(&cp, "Keyboard sends telnet Backspace and Interrupt",
1243                      IDC_TELNETKEY);
1244             endbox(&cp);
1245         }
1246         beginbox(&cp, "Sending of null packets to keep session active",
1247                  IDC_BOX_CONNECTION2);
1248         staticedit(&cp, "Seconds between &keepalives (0 to turn off)",
1249                    IDC_PINGSTATIC, IDC_PINGEDIT, 20);
1250         endbox(&cp);
1251     }
1252
1253     if (panel == telnetpanelstart) {
1254         /* The Telnet panel. Accelerators used: [acgo] svldr bftk */
1255         struct ctlpos cp;
1256         ctlposinit(&cp, hwnd, 80, 3, 13);
1257         if (dlgtype == 0) {
1258             bartitle(&cp, "Options controlling Telnet connections",
1259                      IDC_TITLE_TELNET);
1260             beginbox(&cp, "Data to send to the server", IDC_BOX_TELNET1);
1261             staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC,
1262                        IDC_TSEDIT, 50);
1263             envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1264                       "&Variable", IDC_VARSTATIC, IDC_VAREDIT, "Va&lue",
1265                       IDC_VALSTATIC, IDC_VALEDIT, IDC_ENVLIST, "A&dd",
1266                       IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1267             endbox(&cp);
1268             beginbox(&cp, "Telnet protocol adjustments", IDC_BOX_TELNET2);
1269             radioline(&cp, "Handling of OLD_ENVIRON ambiguity:",
1270                       IDC_EMSTATIC, 2, "&BSD (commonplace)", IDC_EMBSD,
1271                       "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1272             radioline(&cp, "&Telnet negotiation mode:", IDC_ACTSTATIC, 2,
1273                       "Passive", IDC_TPASSIVE, "Active",
1274                       IDC_TACTIVE, NULL);
1275             checkbox(&cp, "&Keyboard sends telnet Backspace and Interrupt",
1276                      IDC_TELNETKEY);
1277             endbox(&cp);
1278         }
1279     }
1280
1281     if (panel == rloginpanelstart) {
1282         /* The Rlogin panel. Accelerators used: [acgo] sl */
1283         struct ctlpos cp;
1284         ctlposinit(&cp, hwnd, 80, 3, 13);
1285         if (dlgtype == 0) {
1286             bartitle(&cp, "Options controlling Rlogin connections",
1287                      IDC_TITLE_RLOGIN);
1288             beginbox(&cp, "Data to send to the server", IDC_BOX_RLOGIN1);
1289             staticedit(&cp, "Terminal-&speed string", IDC_R_TSSTATIC,
1290                        IDC_R_TSEDIT, 50);
1291             staticedit(&cp, "&Local username:", IDC_RLLUSERSTATIC,
1292                        IDC_RLLUSEREDIT, 50);
1293             endbox(&cp);
1294         }
1295     }
1296
1297     if (panel == sshpanelstart) {
1298         /* The SSH panel. Accelerators used: [acgo] r pe12i s */
1299         struct ctlpos cp;
1300         ctlposinit(&cp, hwnd, 80, 3, 13);
1301         if (dlgtype == 0) {
1302             bartitle(&cp, "Options controlling SSH connections",
1303                      IDC_TITLE_SSH);
1304             beginbox(&cp, "Data to send to the server", IDC_BOX_SSH1);
1305             multiedit(&cp,
1306                       "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1307                       NULL);
1308             endbox(&cp);
1309             beginbox(&cp, "Protocol options", IDC_BOX_SSH2);
1310             checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1311             checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
1312             radioline(&cp, "Preferred SSH protocol version:",
1313                       IDC_SSHPROTSTATIC, 2,
1314                       "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1315             checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1316                      IDC_BUGGYMAC);
1317             endbox(&cp);
1318             beginbox(&cp, "Encryption options", IDC_BOX_SSH3);
1319             prefslist(&cipherlist, &cp, "Encryption cipher &selection policy:",
1320                       IDC_CIPHERSTATIC2, IDC_CIPHERLIST, IDC_CIPHERUP,
1321                       IDC_CIPHERDN);
1322             endbox(&cp);
1323         }
1324     }
1325
1326     if (panel == sshauthpanelstart) {
1327         /* The SSH authentication panel. Accelerators used: [acgo] m fkiw */
1328         struct ctlpos cp;
1329         ctlposinit(&cp, hwnd, 80, 3, 13);
1330         if (dlgtype == 0) {
1331             bartitle(&cp, "Options controlling SSH authentication",
1332                      IDC_TITLE_SSHAUTH);
1333             beginbox(&cp, "Authentication methods",
1334                      IDC_BOX_SSHAUTH1);
1335             checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication (SSH1)",
1336                      IDC_AUTHTIS);
1337             checkbox(&cp, "Attempt \"keyboard-&interactive\" authentication"
1338                      " (SSH2)", IDC_AUTHKI);
1339             endbox(&cp);
1340             beginbox(&cp, "Authentication parameters",
1341                      IDC_BOX_SSHAUTH2);
1342             checkbox(&cp, "Allow agent &forwarding", IDC_AGENTFWD);
1343             editbutton(&cp, "Private &key file for authentication:",
1344                        IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...",
1345                        IDC_PKBUTTON);
1346             endbox(&cp);
1347         }
1348     }
1349
1350     if (panel == tunnelspanelstart) {
1351         /* The Tunnels panel. Accelerators used: [acgo] deilmrstx */
1352         struct ctlpos cp;
1353         ctlposinit(&cp, hwnd, 80, 3, 13);
1354         if (dlgtype == 0) {
1355             bartitle(&cp, "Options controlling SSH tunnelling",
1356                      IDC_TITLE_TUNNELS);
1357             beginbox(&cp, "X11 forwarding", IDC_BOX_TUNNELS1);
1358             checkbox(&cp, "&Enable X11 forwarding", IDC_X11_FORWARD);
1359             multiedit(&cp, "&X display location", IDC_X11_DISPSTATIC,
1360                       IDC_X11_DISPLAY, 50, NULL);
1361             endbox(&cp);
1362             beginbox(&cp, "Port forwarding", IDC_BOX_TUNNELS2);
1363             checkbox(&cp, "Local ports accept connections from o&ther hosts", IDC_LPORT_ALL);
1364             staticbtn(&cp, "Forwarded ports:", IDC_PFWDSTATIC,
1365                       "&Remove", IDC_PFWDREMOVE);
1366             fwdsetter(&cp, IDC_PFWDLIST,
1367                       "Add new forwarded port:", IDC_PFWDSTATIC2,
1368                       "&Source port", IDC_SPORTSTATIC, IDC_SPORTEDIT,
1369                       "Dest&ination", IDC_DPORTSTATIC, IDC_DPORTEDIT,
1370                       "A&dd", IDC_PFWDADD);
1371             bareradioline(&cp, 2,
1372                           "&Local", IDC_PFWDLOCAL, "Re&mote", IDC_PFWDREMOTE, NULL);
1373             endbox(&cp);
1374
1375         }
1376     }
1377 }
1378
1379 /* 
1380  * Helper function to load the session selected in SESSLIST
1381  * if any, as this is done in more than one place in
1382  * GenericMainDlgProc(). 0 => failure.
1383  */
1384 static int load_selected_session(HWND hwnd)
1385 {
1386     int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1387                                LB_GETCURSEL, 0, 0);
1388     int isdef;
1389     if (n == LB_ERR) {
1390         MessageBeep(0);
1391         return 0;
1392     }
1393     isdef = !strcmp(sessions[n], "Default Settings");
1394     load_settings(sessions[n], !isdef, &cfg);
1395     init_dlg_ctrls(hwnd, TRUE);
1396     if (!isdef)
1397         SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1398     else
1399         SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1400     /* Restore the selection, which will have been clobbered by
1401      * SESSEDIT handling. */
1402     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL, n, 0);
1403     return 1;
1404 }
1405
1406 /*
1407  * This function is the configuration box.
1408  */
1409 static int GenericMainDlgProc(HWND hwnd, UINT msg,
1410                               WPARAM wParam, LPARAM lParam, int dlgtype)
1411 {
1412     HWND hw, treeview;
1413     struct treeview_faff tvfaff;
1414     HTREEITEM hsession;
1415     OPENFILENAME of;
1416     char filename[sizeof(cfg.keyfile)];
1417     CHOOSEFONT cf;
1418     LOGFONT lf;
1419     char fontstatic[256];
1420     char portname[32];
1421     struct servent *service;
1422     int i;
1423     static UINT draglistmsg = WM_NULL;
1424
1425     switch (msg) {
1426       case WM_INITDIALOG:
1427         readytogo = 0;
1428         SetWindowLong(hwnd, GWL_USERDATA, 0);
1429         SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
1430                     (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(IDI_CFGICON)));
1431         /*
1432          * Centre the window.
1433          */
1434         {                              /* centre the window */
1435             RECT rs, rd;
1436
1437             hw = GetDesktopWindow();
1438             if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))
1439                 MoveWindow(hwnd,
1440                            (rs.right + rs.left + rd.left - rd.right) / 2,
1441                            (rs.bottom + rs.top + rd.top - rd.bottom) / 2,
1442                            rd.right - rd.left, rd.bottom - rd.top, TRUE);
1443         }
1444
1445         /*
1446          * Create the tree view.
1447          */
1448         {
1449             RECT r;
1450             WPARAM font;
1451             HWND tvstatic;
1452
1453             r.left = 3;
1454             r.right = r.left + 75;
1455             r.top = 3;
1456             r.bottom = r.top + 10;
1457             MapDialogRect(hwnd, &r);
1458             tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1459                                       WS_CHILD | WS_VISIBLE,
1460                                       r.left, r.top,
1461                                       r.right - r.left, r.bottom - r.top,
1462                                       hwnd, (HMENU) IDCX_TVSTATIC, hinst,
1463                                       NULL);
1464             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1465             SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1466
1467             r.left = 3;
1468             r.right = r.left + 75;
1469             r.top = 13;
1470             r.bottom = r.top + 219;
1471             MapDialogRect(hwnd, &r);
1472             treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1473                                       WS_CHILD | WS_VISIBLE |
1474                                       WS_TABSTOP | TVS_HASLINES |
1475                                       TVS_DISABLEDRAGDROP | TVS_HASBUTTONS
1476                                       | TVS_LINESATROOT |
1477                                       TVS_SHOWSELALWAYS, r.left, r.top,
1478                                       r.right - r.left, r.bottom - r.top,
1479                                       hwnd, (HMENU) IDCX_TREEVIEW, hinst,
1480                                       NULL);
1481             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1482             SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1483             tvfaff.treeview = treeview;
1484             memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1485         }
1486
1487         /*
1488          * Set up the tree view contents.
1489          */
1490         hsession = treeview_insert(&tvfaff, 0, "Session");
1491         treeview_insert(&tvfaff, 1, "Logging");
1492         treeview_insert(&tvfaff, 0, "Terminal");
1493         treeview_insert(&tvfaff, 1, "Keyboard");
1494         treeview_insert(&tvfaff, 1, "Bell");
1495         treeview_insert(&tvfaff, 0, "Window");
1496         treeview_insert(&tvfaff, 1, "Appearance");
1497         treeview_insert(&tvfaff, 1, "Behaviour");
1498         treeview_insert(&tvfaff, 1, "Translation");
1499         treeview_insert(&tvfaff, 1, "Selection");
1500         treeview_insert(&tvfaff, 1, "Colours");
1501         treeview_insert(&tvfaff, 0, "Connection");
1502         if (dlgtype == 0) {
1503             treeview_insert(&tvfaff, 1, "Telnet");
1504             treeview_insert(&tvfaff, 1, "Rlogin");
1505             if (backends[3].backend != NULL) {
1506                 treeview_insert(&tvfaff, 1, "SSH");
1507                 /* XXX long name is ugly */
1508                 /* XXX make it closed by default? */
1509                 treeview_insert(&tvfaff, 2, "Auth");
1510                 treeview_insert(&tvfaff, 2, "Tunnels");
1511             }
1512         }
1513
1514         /*
1515          * Put the treeview selection on to the Session panel. This
1516          * should also cause creation of the relevant controls.
1517          */
1518         TreeView_SelectItem(treeview, hsession);
1519
1520         /*
1521          * Set focus into the first available control.
1522          */
1523         {
1524             HWND ctl;
1525             ctl = GetDlgItem(hwnd, IDC_HOST);
1526             if (!ctl)
1527                 ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1528             SetFocus(ctl);
1529         }
1530
1531         SetWindowLong(hwnd, GWL_USERDATA, 1);
1532         sesslist_has_focus = 0;
1533         return 0;
1534       case WM_LBUTTONUP:
1535         /*
1536          * Button release should trigger WM_OK if there was a
1537          * previous double click on the session list.
1538          */
1539         ReleaseCapture();
1540         if (readytogo)
1541             SendMessage(hwnd, WM_COMMAND, IDOK, 0);
1542         break;
1543       case WM_NOTIFY:
1544         if (LOWORD(wParam) == IDCX_TREEVIEW &&
1545             ((LPNMHDR) lParam)->code == TVN_SELCHANGED) {
1546             HTREEITEM i =
1547                 TreeView_GetSelection(((LPNMHDR) lParam)->hwndFrom);
1548             TVITEM item;
1549             int j;
1550             char buffer[64];
1551  
1552             SendMessage (hwnd, WM_SETREDRAW, FALSE, 0);
1553  
1554             item.hItem = i;
1555             item.pszText = buffer;
1556             item.cchTextMax = sizeof(buffer);
1557             item.mask = TVIF_TEXT;
1558             TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &item);
1559             for (j = controlstartvalue; j < controlendvalue; j++) {
1560                 HWND item = GetDlgItem(hwnd, j);
1561                 if (item)
1562                     DestroyWindow(item);
1563             }
1564             if (!strcmp(buffer, "Session"))
1565                 create_controls(hwnd, dlgtype, sessionpanelstart);
1566             if (!strcmp(buffer, "Logging"))
1567                 create_controls(hwnd, dlgtype, loggingpanelstart);
1568             if (!strcmp(buffer, "Keyboard"))
1569                 create_controls(hwnd, dlgtype, keyboardpanelstart);
1570             if (!strcmp(buffer, "Terminal"))
1571                 create_controls(hwnd, dlgtype, terminalpanelstart);
1572             if (!strcmp(buffer, "Bell"))
1573                 create_controls(hwnd, dlgtype, bellpanelstart);
1574             if (!strcmp(buffer, "Window"))
1575                 create_controls(hwnd, dlgtype, windowpanelstart);
1576             if (!strcmp(buffer, "Appearance"))
1577                 create_controls(hwnd, dlgtype, appearancepanelstart);
1578             if (!strcmp(buffer, "Behaviour"))
1579                 create_controls(hwnd, dlgtype, behaviourpanelstart);
1580             if (!strcmp(buffer, "Tunnels"))
1581                 create_controls(hwnd, dlgtype, tunnelspanelstart);
1582             if (!strcmp(buffer, "Connection"))
1583                 create_controls(hwnd, dlgtype, connectionpanelstart);
1584             if (!strcmp(buffer, "Telnet"))
1585                 create_controls(hwnd, dlgtype, telnetpanelstart);
1586             if (!strcmp(buffer, "Rlogin"))
1587                 create_controls(hwnd, dlgtype, rloginpanelstart);
1588             if (!strcmp(buffer, "SSH"))
1589                 create_controls(hwnd, dlgtype, sshpanelstart);
1590             if (!strcmp(buffer, "Auth"))
1591                 create_controls(hwnd, dlgtype, sshauthpanelstart);
1592             if (!strcmp(buffer, "Selection"))
1593                 create_controls(hwnd, dlgtype, selectionpanelstart);
1594             if (!strcmp(buffer, "Colours"))
1595                 create_controls(hwnd, dlgtype, colourspanelstart);
1596             if (!strcmp(buffer, "Translation"))
1597                 create_controls(hwnd, dlgtype, translationpanelstart);
1598
1599             init_dlg_ctrls(hwnd, FALSE);
1600  
1601             SendMessage (hwnd, WM_SETREDRAW, TRUE, 0);
1602             InvalidateRect (hwnd, NULL, TRUE);
1603
1604             SetFocus(((LPNMHDR) lParam)->hwndFrom);     /* ensure focus stays */
1605             return 0;
1606         }
1607         break;
1608       case WM_COMMAND:
1609         /*
1610          * Only process WM_COMMAND once the dialog is fully formed.
1611          */
1612         if (GetWindowLong(hwnd, GWL_USERDATA) == 1)
1613             switch (LOWORD(wParam)) {
1614               case IDOK:
1615                 /* Behaviour of the "Open" button is different if the
1616                  * session list has focus, *unless* the user just
1617                  * double-clicked... */
1618                 if (sesslist_has_focus && !readytogo) {
1619                     if (!load_selected_session(hwnd)) {
1620                         MessageBeep(0);
1621                         return 0;
1622                     }
1623                 }
1624                 /* If at this point we have a valid session, go! */
1625                 if (*cfg.host)
1626                     EndDialog(hwnd, 1);
1627                 else
1628                     MessageBeep(0);
1629                 return 0;
1630               case IDCANCEL:
1631                 EndDialog(hwnd, 0);
1632                 return 0;
1633               case IDC_PROTTELNET:
1634               case IDC_PROTRLOGIN:
1635               case IDC_PROTSSH:
1636               case IDC_PROTRAW:
1637                 if (HIWORD(wParam) == BN_CLICKED ||
1638                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1639                     int i = IsDlgButtonChecked(hwnd, IDC_PROTSSH);
1640                     int j = IsDlgButtonChecked(hwnd, IDC_PROTTELNET);
1641                     int k = IsDlgButtonChecked(hwnd, IDC_PROTRLOGIN);
1642                     cfg.protocol =
1643                         i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN :
1644                         PROT_RAW;
1645                     if ((cfg.protocol == PROT_SSH && cfg.port != 22)
1646                         || (cfg.protocol == PROT_TELNET && cfg.port != 23)
1647                         || (cfg.protocol == PROT_RLOGIN
1648                             && cfg.port != 513)) {
1649                         cfg.port = i ? 22 : j ? 23 : 513;
1650                         SetDlgItemInt(hwnd, IDC_PORT, cfg.port, FALSE);
1651                     }
1652                 }
1653                 break;
1654               case IDC_HOST:
1655                 if (HIWORD(wParam) == EN_CHANGE)
1656                     GetDlgItemText(hwnd, IDC_HOST, cfg.host,
1657                                    sizeof(cfg.host) - 1);
1658                 break;
1659               case IDC_PORT:
1660                 if (HIWORD(wParam) == EN_CHANGE) {
1661                     GetDlgItemText(hwnd, IDC_PORT, portname, 31);
1662                     if (isdigit(portname[0]))
1663                         MyGetDlgItemInt(hwnd, IDC_PORT, &cfg.port);
1664                     else {
1665                         service = getservbyname(portname, NULL);
1666                         if (service)
1667                             cfg.port = ntohs(service->s_port);
1668                         else
1669                             cfg.port = 0;
1670                     }
1671                 }
1672                 break;
1673               case IDC_SESSEDIT:
1674                 if (HIWORD(wParam) == EN_CHANGE) {
1675                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1676                                        (WPARAM) - 1, 0);
1677                     GetDlgItemText(hwnd, IDC_SESSEDIT,
1678                                    savedsession, sizeof(savedsession) - 1);
1679                     savedsession[sizeof(savedsession) - 1] = '\0';
1680                 }
1681                 break;
1682               case IDC_SESSSAVE:
1683                 if (HIWORD(wParam) == BN_CLICKED ||
1684                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1685                     /*
1686                      * Save a session
1687                      */
1688                     char str[2048];
1689                     GetDlgItemText(hwnd, IDC_SESSEDIT, str,
1690                                    sizeof(str) - 1);
1691                     if (!*str) {
1692                         int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1693                                                    LB_GETCURSEL, 0, 0);
1694                         if (n == LB_ERR) {
1695                             MessageBeep(0);
1696                             break;
1697                         }
1698                         strcpy(str, sessions[n]);
1699                     }
1700                     save_settings(str, !!strcmp(str, "Default Settings"),
1701                                   &cfg);
1702                     get_sesslist(FALSE);
1703                     get_sesslist(TRUE);
1704                     SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
1705                                        FALSE, 0);
1706                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1707                                        0, 0);
1708                     for (i = 0; i < nsessions; i++)
1709                         SendDlgItemMessage(hwnd, IDC_SESSLIST,
1710                                            LB_ADDSTRING, 0,
1711                                            (LPARAM) (sessions[i]));
1712                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1713                                        (WPARAM) - 1, 0);
1714                     SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
1715                                        TRUE, 0);
1716                     InvalidateRect(GetDlgItem(hwnd, IDC_SESSLIST), NULL,
1717                                    TRUE);
1718                 }
1719                 break;
1720               case IDC_SESSLIST:
1721               case IDC_SESSLOAD:
1722                 if (LOWORD(wParam) == IDC_SESSLIST) {
1723                     if (HIWORD(wParam) == LBN_SETFOCUS)
1724                         sesslist_has_focus = 1;
1725                     else if (HIWORD(wParam) == LBN_KILLFOCUS)
1726                         sesslist_has_focus = 0;
1727                 }
1728                 if (LOWORD(wParam) == IDC_SESSLOAD &&
1729                     HIWORD(wParam) != BN_CLICKED &&
1730                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
1731                 if (LOWORD(wParam) == IDC_SESSLIST &&
1732                     HIWORD(wParam) != LBN_DBLCLK) break;
1733                 /* Load the session selected in SESSLIST. */
1734                 if (load_selected_session(hwnd) &&
1735                     LOWORD(wParam) == IDC_SESSLIST) {
1736                     /*
1737                      * A double-click on a saved session should
1738                      * actually start the session, not just load it.
1739                      * Unless it's Default Settings or some other
1740                      * host-less set of saved settings.
1741                      */
1742                     if (*cfg.host) {
1743                         readytogo = TRUE;
1744                         SetCapture(hwnd);
1745                     }
1746                 }
1747                 break;
1748               case IDC_SESSDEL:
1749                 if (HIWORD(wParam) == BN_CLICKED ||
1750                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1751                     int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1752                                                LB_GETCURSEL, 0, 0);
1753                     if (n == LB_ERR || n == 0) {
1754                         MessageBeep(0);
1755                         break;
1756                     }
1757                     del_settings(sessions[n]);
1758                     get_sesslist(FALSE);
1759                     get_sesslist(TRUE);
1760                     SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
1761                                        FALSE, 0);
1762                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1763                                        0, 0);
1764                     for (i = 0; i < nsessions; i++)
1765                         SendDlgItemMessage(hwnd, IDC_SESSLIST,
1766                                            LB_ADDSTRING, 0,
1767                                            (LPARAM) (sessions[i]));
1768                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1769                                        (WPARAM) - 1, 0);
1770                     SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
1771                                        TRUE, 0);
1772                     InvalidateRect(GetDlgItem(hwnd, IDC_SESSLIST), NULL,
1773                                    TRUE);
1774                 }
1775               case IDC_PINGEDIT:
1776                 if (HIWORD(wParam) == EN_CHANGE)
1777                     MyGetDlgItemInt(hwnd, IDC_PINGEDIT,
1778                                     &cfg.ping_interval);
1779                 break;
1780               case IDC_DEL008:
1781               case IDC_DEL127:
1782                 if (HIWORD(wParam) == BN_CLICKED ||
1783                     HIWORD(wParam) == BN_DOUBLECLICKED)
1784                         cfg.bksp_is_delete =
1785                         IsDlgButtonChecked(hwnd, IDC_DEL127);
1786                 break;
1787               case IDC_HOMETILDE:
1788               case IDC_HOMERXVT:
1789                 if (HIWORD(wParam) == BN_CLICKED ||
1790                     HIWORD(wParam) == BN_DOUBLECLICKED)
1791                         cfg.rxvt_homeend =
1792                         IsDlgButtonChecked(hwnd, IDC_HOMERXVT);
1793                 break;
1794               case IDC_FUNCTILDE:
1795               case IDC_FUNCLINUX:
1796               case IDC_FUNCXTERM:
1797               case IDC_FUNCVT400:
1798               case IDC_FUNCVT100P:
1799               case IDC_FUNCSCO:
1800                 if (HIWORD(wParam) == BN_CLICKED ||
1801                     HIWORD(wParam) == BN_DOUBLECLICKED)
1802                         switch (LOWORD(wParam)) {
1803                       case IDC_FUNCTILDE:
1804                         cfg.funky_type = 0;
1805                         break;
1806                       case IDC_FUNCLINUX:
1807                         cfg.funky_type = 1;
1808                         break;
1809                       case IDC_FUNCXTERM:
1810                         cfg.funky_type = 2;
1811                         break;
1812                       case IDC_FUNCVT400:
1813                         cfg.funky_type = 3;
1814                         break;
1815                       case IDC_FUNCVT100P:
1816                         cfg.funky_type = 4;
1817                         break;
1818                       case IDC_FUNCSCO:
1819                         cfg.funky_type = 5;
1820                         break;
1821                     }
1822                 break;
1823               case IDC_KPNORMAL:
1824               case IDC_KPAPPLIC:
1825                 if (HIWORD(wParam) == BN_CLICKED ||
1826                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1827                     cfg.app_keypad =
1828                         IsDlgButtonChecked(hwnd, IDC_KPAPPLIC);
1829                     cfg.nethack_keypad = FALSE;
1830                 }
1831                 break;
1832               case IDC_KPNH:
1833                 if (HIWORD(wParam) == BN_CLICKED ||
1834                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1835                     cfg.app_keypad = FALSE;
1836                     cfg.nethack_keypad = TRUE;
1837                 }
1838                 break;
1839               case IDC_CURNORMAL:
1840               case IDC_CURAPPLIC:
1841                 if (HIWORD(wParam) == BN_CLICKED ||
1842                     HIWORD(wParam) == BN_DOUBLECLICKED)
1843                         cfg.app_cursor =
1844                         IsDlgButtonChecked(hwnd, IDC_CURAPPLIC);
1845                 break;
1846               case IDC_NOAPPLICC:
1847                 if (HIWORD(wParam) == BN_CLICKED ||
1848                     HIWORD(wParam) == BN_DOUBLECLICKED)
1849                         cfg.no_applic_c =
1850                         IsDlgButtonChecked(hwnd, IDC_NOAPPLICC);
1851                 break;
1852               case IDC_NOAPPLICK:
1853                 if (HIWORD(wParam) == BN_CLICKED ||
1854                     HIWORD(wParam) == BN_DOUBLECLICKED)
1855                         cfg.no_applic_k =
1856                         IsDlgButtonChecked(hwnd, IDC_NOAPPLICK);
1857                 break;
1858               case IDC_ALTF4:
1859                 if (HIWORD(wParam) == BN_CLICKED ||
1860                     HIWORD(wParam) == BN_DOUBLECLICKED)
1861                         cfg.alt_f4 = IsDlgButtonChecked(hwnd, IDC_ALTF4);
1862                 break;
1863               case IDC_ALTSPACE:
1864                 if (HIWORD(wParam) == BN_CLICKED ||
1865                     HIWORD(wParam) == BN_DOUBLECLICKED)
1866                         cfg.alt_space =
1867                         IsDlgButtonChecked(hwnd, IDC_ALTSPACE);
1868                 break;
1869               case IDC_ALTONLY:
1870                 if (HIWORD(wParam) == BN_CLICKED ||
1871                     HIWORD(wParam) == BN_DOUBLECLICKED)
1872                         cfg.alt_only =
1873                         IsDlgButtonChecked(hwnd, IDC_ALTONLY);
1874                 break;
1875               case IDC_ECHOBACKEND:
1876               case IDC_ECHOYES:
1877               case IDC_ECHONO:
1878                 if (HIWORD(wParam) == BN_CLICKED ||
1879                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1880                     if (LOWORD(wParam) == IDC_ECHOBACKEND)
1881                         cfg.localecho = LD_BACKEND;
1882                     if (LOWORD(wParam) == IDC_ECHOYES)
1883                         cfg.localecho = LD_YES;
1884                     if (LOWORD(wParam) == IDC_ECHONO)
1885                         cfg.localecho = LD_NO;
1886                 }
1887                 break;
1888               case IDC_EDITBACKEND:
1889               case IDC_EDITYES:
1890               case IDC_EDITNO:
1891                 if (HIWORD(wParam) == BN_CLICKED ||
1892                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1893                     if (LOWORD(wParam) == IDC_EDITBACKEND)
1894                         cfg.localedit = LD_BACKEND;
1895                     if (LOWORD(wParam) == IDC_EDITYES)
1896                         cfg.localedit = LD_YES;
1897                     if (LOWORD(wParam) == IDC_EDITNO)
1898                         cfg.localedit = LD_NO;
1899                 }
1900                 break;
1901               case IDC_ANSWEREDIT:
1902                 if (HIWORD(wParam) == EN_CHANGE)
1903                     GetDlgItemText(hwnd, IDC_ANSWEREDIT, cfg.answerback,
1904                                    sizeof(cfg.answerback) - 1);
1905                 break;
1906               case IDC_ALWAYSONTOP:
1907                 if (HIWORD(wParam) == BN_CLICKED ||
1908                     HIWORD(wParam) == BN_DOUBLECLICKED)
1909                         cfg.alwaysontop =
1910                         IsDlgButtonChecked(hwnd, IDC_ALWAYSONTOP);
1911                 break;
1912               case IDC_FULLSCREENONALTENTER:
1913                 if (HIWORD(wParam) == BN_CLICKED ||
1914                     HIWORD(wParam) == BN_DOUBLECLICKED)
1915                         cfg.fullscreenonaltenter =
1916                         IsDlgButtonChecked(hwnd, IDC_FULLSCREENONALTENTER);
1917                 break;
1918               case IDC_SCROLLKEY:
1919                 if (HIWORD(wParam) == BN_CLICKED ||
1920                     HIWORD(wParam) == BN_DOUBLECLICKED)
1921                         cfg.scroll_on_key =
1922                         IsDlgButtonChecked(hwnd, IDC_SCROLLKEY);
1923                 break;
1924               case IDC_SCROLLDISP:
1925                 if (HIWORD(wParam) == BN_CLICKED ||
1926                     HIWORD(wParam) == BN_DOUBLECLICKED)
1927                         cfg.scroll_on_disp =
1928                         IsDlgButtonChecked(hwnd, IDC_SCROLLDISP);
1929                 break;
1930               case IDC_COMPOSEKEY:
1931                 if (HIWORD(wParam) == BN_CLICKED ||
1932                     HIWORD(wParam) == BN_DOUBLECLICKED)
1933                         cfg.compose_key =
1934                         IsDlgButtonChecked(hwnd, IDC_COMPOSEKEY);
1935                 break;
1936               case IDC_CTRLALTKEYS:
1937                 if (HIWORD(wParam) == BN_CLICKED ||
1938                     HIWORD(wParam) == BN_DOUBLECLICKED)
1939                         cfg.ctrlaltkeys =
1940                         IsDlgButtonChecked(hwnd, IDC_CTRLALTKEYS);
1941                 break;
1942               case IDC_TELNETKEY:
1943                 if (HIWORD(wParam) == BN_CLICKED ||
1944                     HIWORD(wParam) == BN_DOUBLECLICKED)
1945                         cfg.telnet_keyboard =
1946                         IsDlgButtonChecked(hwnd, IDC_TELNETKEY);
1947                 break;
1948               case IDC_WRAPMODE:
1949                 if (HIWORD(wParam) == BN_CLICKED ||
1950                     HIWORD(wParam) == BN_DOUBLECLICKED)
1951                         cfg.wrap_mode =
1952                         IsDlgButtonChecked(hwnd, IDC_WRAPMODE);
1953                 break;
1954               case IDC_DECOM:
1955                 if (HIWORD(wParam) == BN_CLICKED ||
1956                     HIWORD(wParam) == BN_DOUBLECLICKED)
1957                         cfg.dec_om = IsDlgButtonChecked(hwnd, IDC_DECOM);
1958                 break;
1959               case IDC_LFHASCR:
1960                 if (HIWORD(wParam) == BN_CLICKED ||
1961                     HIWORD(wParam) == BN_DOUBLECLICKED)
1962                         cfg.lfhascr =
1963                         IsDlgButtonChecked(hwnd, IDC_LFHASCR);
1964                 break;
1965               case IDC_ROWSEDIT:
1966                 if (HIWORD(wParam) == EN_CHANGE)
1967                     MyGetDlgItemInt(hwnd, IDC_ROWSEDIT, &cfg.height);
1968                 break;
1969               case IDC_COLSEDIT:
1970                 if (HIWORD(wParam) == EN_CHANGE)
1971                     MyGetDlgItemInt(hwnd, IDC_COLSEDIT, &cfg.width);
1972                 break;
1973               case IDC_SAVEEDIT:
1974                 if (HIWORD(wParam) == EN_CHANGE)
1975                     MyGetDlgItemInt(hwnd, IDC_SAVEEDIT, &cfg.savelines);
1976                 break;
1977               case IDC_CHOOSEFONT:
1978                 {
1979                     HDC hdc = GetDC(0);
1980                     lf.lfHeight = -MulDiv(cfg.fontheight,
1981                                           GetDeviceCaps(hdc, LOGPIXELSY),
1982                                           72);
1983                     ReleaseDC(0, hdc);
1984                 }
1985                 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1986                 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1987                 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1988                 lf.lfCharSet = cfg.fontcharset;
1989                 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1990                 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1991                 lf.lfQuality = DEFAULT_QUALITY;
1992                 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1993                 strncpy(lf.lfFaceName, cfg.font,
1994                         sizeof(lf.lfFaceName) - 1);
1995                 lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
1996
1997                 cf.lStructSize = sizeof(cf);
1998                 cf.hwndOwner = hwnd;
1999                 cf.lpLogFont = &lf;
2000                 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
2001                     CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
2002
2003                 if (ChooseFont(&cf)) {
2004                     strncpy(cfg.font, lf.lfFaceName, sizeof(cfg.font) - 1);
2005                     cfg.font[sizeof(cfg.font) - 1] = '\0';
2006                     cfg.fontisbold = (lf.lfWeight == FW_BOLD);
2007                     cfg.fontcharset = lf.lfCharSet;
2008                     cfg.fontheight = cf.iPointSize / 10;
2009                     fmtfont(fontstatic);
2010                     SetDlgItemText(hwnd, IDC_FONTSTATIC, fontstatic);
2011                 }
2012                 break;
2013               case IDC_BELL_DISABLED:
2014               case IDC_BELL_DEFAULT:
2015               case IDC_BELL_WAVEFILE:
2016               case IDC_BELL_VISUAL:
2017                 if (HIWORD(wParam) == BN_CLICKED ||
2018                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2019                     if (LOWORD(wParam) == IDC_BELL_DISABLED)
2020                         cfg.beep = BELL_DISABLED;
2021                     if (LOWORD(wParam) == IDC_BELL_DEFAULT)
2022                         cfg.beep = BELL_DEFAULT;
2023                     if (LOWORD(wParam) == IDC_BELL_WAVEFILE)
2024                         cfg.beep = BELL_WAVEFILE;
2025                     if (LOWORD(wParam) == IDC_BELL_VISUAL)
2026                         cfg.beep = BELL_VISUAL;
2027                 }
2028                 break;
2029               case IDC_B_IND_DISABLED:
2030               case IDC_B_IND_FLASH:
2031               case IDC_B_IND_STEADY:
2032                 if (HIWORD(wParam) == BN_CLICKED ||
2033                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2034                     if (LOWORD(wParam) == IDC_B_IND_DISABLED)
2035                         cfg.beep_ind = B_IND_DISABLED;
2036                     if (LOWORD(wParam) == IDC_B_IND_FLASH)
2037                         cfg.beep_ind = B_IND_FLASH;
2038                     if (LOWORD(wParam) == IDC_B_IND_STEADY)
2039                         cfg.beep_ind = B_IND_STEADY;
2040                 }
2041                 break;
2042               case IDC_BELL_WAVEBROWSE:
2043                 memset(&of, 0, sizeof(of));
2044 #ifdef OPENFILENAME_SIZE_VERSION_400
2045                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2046 #else
2047                 of.lStructSize = sizeof(of);
2048 #endif
2049                 of.hwndOwner = hwnd;
2050                 of.lpstrFilter = "Wave Files\0*.WAV\0AllFiles\0*\0\0\0";
2051                 of.lpstrCustomFilter = NULL;
2052                 of.nFilterIndex = 1;
2053                 of.lpstrFile = filename;
2054                 strcpy(filename, cfg.bell_wavefile);
2055                 of.nMaxFile = sizeof(filename);
2056                 of.lpstrFileTitle = NULL;
2057                 of.lpstrInitialDir = NULL;
2058                 of.lpstrTitle = "Select Bell Sound File";
2059                 of.Flags = 0;
2060                 if (GetOpenFileName(&of)) {
2061                     strcpy(cfg.bell_wavefile, filename);
2062                     SetDlgItemText(hwnd, IDC_BELL_WAVEEDIT,
2063                                    cfg.bell_wavefile);
2064                 }
2065                 break;
2066               case IDC_BELL_WAVEEDIT:
2067                 if (HIWORD(wParam) == EN_CHANGE)
2068                     GetDlgItemText(hwnd, IDC_BELL_WAVEEDIT,
2069                                    cfg.bell_wavefile,
2070                                    sizeof(cfg.bell_wavefile) - 1);
2071                 break;
2072               case IDC_BELLOVL:
2073                 if (HIWORD(wParam) == BN_CLICKED ||
2074                     HIWORD(wParam) == BN_DOUBLECLICKED)
2075                         cfg.bellovl =
2076                         IsDlgButtonChecked(hwnd, IDC_BELLOVL);
2077                 break;
2078               case IDC_BELLOVLN:
2079                 if (HIWORD(wParam) == EN_CHANGE)
2080                     MyGetDlgItemInt(hwnd, IDC_BELLOVLN, &cfg.bellovl_n);
2081                 break;
2082               case IDC_BELLOVLT:
2083                 if (HIWORD(wParam) == EN_CHANGE)
2084                     MyGetDlgItemFlt(hwnd, IDC_BELLOVLT, &cfg.bellovl_t,
2085                                     1000);
2086                 break;
2087               case IDC_BELLOVLS:
2088                 if (HIWORD(wParam) == EN_CHANGE)
2089                     MyGetDlgItemFlt(hwnd, IDC_BELLOVLS, &cfg.bellovl_s,
2090                                     1000);
2091                 break;
2092               case IDC_BLINKTEXT:
2093                 if (HIWORD(wParam) == BN_CLICKED ||
2094                     HIWORD(wParam) == BN_DOUBLECLICKED)
2095                         cfg.blinktext =
2096                         IsDlgButtonChecked(hwnd, IDC_BLINKTEXT);
2097                 break;
2098               case IDC_BCE:
2099                 if (HIWORD(wParam) == BN_CLICKED ||
2100                     HIWORD(wParam) == BN_DOUBLECLICKED)
2101                         cfg.bce = IsDlgButtonChecked(hwnd, IDC_BCE);
2102                 break;
2103               case IDC_WINNAME:
2104                 if (HIWORD(wParam) == BN_CLICKED ||
2105                     HIWORD(wParam) == BN_DOUBLECLICKED)
2106                         cfg.win_name_always =
2107                         IsDlgButtonChecked(hwnd, IDC_WINNAME);
2108                 break;
2109               case IDC_HIDEMOUSE:
2110                 if (HIWORD(wParam) == BN_CLICKED ||
2111                     HIWORD(wParam) == BN_DOUBLECLICKED)
2112                         cfg.hide_mouseptr =
2113                         IsDlgButtonChecked(hwnd, IDC_HIDEMOUSE);
2114                 break;
2115               case IDC_SUNKENEDGE:
2116                 if (HIWORD(wParam) == BN_CLICKED ||
2117                     HIWORD(wParam) == BN_DOUBLECLICKED)
2118                         cfg.sunken_edge =
2119                         IsDlgButtonChecked(hwnd, IDC_SUNKENEDGE);
2120                 break;
2121               case IDC_WINBEDIT:
2122                 if (HIWORD(wParam) == EN_CHANGE)
2123                     MyGetDlgItemInt(hwnd, IDC_WINBEDIT,
2124                                     &cfg.window_border);
2125                 if (cfg.window_border > 32)
2126                     cfg.window_border = 32;
2127                 break;
2128               case IDC_CURBLOCK:
2129                 if (HIWORD(wParam) == BN_CLICKED ||
2130                     HIWORD(wParam) == BN_DOUBLECLICKED)
2131                         cfg.cursor_type = 0;
2132                 break;
2133               case IDC_CURUNDER:
2134                 if (HIWORD(wParam) == BN_CLICKED ||
2135                     HIWORD(wParam) == BN_DOUBLECLICKED)
2136                         cfg.cursor_type = 1;
2137                 break;
2138               case IDC_CURVERT:
2139                 if (HIWORD(wParam) == BN_CLICKED ||
2140                     HIWORD(wParam) == BN_DOUBLECLICKED)
2141                         cfg.cursor_type = 2;
2142                 break;
2143               case IDC_BLINKCUR:
2144                 if (HIWORD(wParam) == BN_CLICKED ||
2145                     HIWORD(wParam) == BN_DOUBLECLICKED)
2146                         cfg.blink_cur =
2147                         IsDlgButtonChecked(hwnd, IDC_BLINKCUR);
2148                 break;
2149               case IDC_SCROLLBAR:
2150                 if (HIWORD(wParam) == BN_CLICKED ||
2151                     HIWORD(wParam) == BN_DOUBLECLICKED)
2152                         cfg.scrollbar =
2153                         IsDlgButtonChecked(hwnd, IDC_SCROLLBAR);
2154                 break;
2155               case IDC_SCROLLBARFULLSCREEN:
2156                 if (HIWORD(wParam) == BN_CLICKED ||
2157                     HIWORD(wParam) == BN_DOUBLECLICKED)
2158                     cfg.scrollbar_in_fullscreen =
2159                     IsDlgButtonChecked(hwnd, IDC_SCROLLBARFULLSCREEN);
2160                 break;
2161               case IDC_RESIZETERM:
2162               case IDC_RESIZEFONT:
2163               case IDC_RESIZENONE:
2164               case IDC_RESIZEEITHER:
2165                 if (HIWORD(wParam) == BN_CLICKED ||
2166                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2167                     cfg.resize_action =
2168                         IsDlgButtonChecked(hwnd,
2169                                            IDC_RESIZETERM) ? RESIZE_TERM :
2170                         IsDlgButtonChecked(hwnd,
2171                                            IDC_RESIZEFONT) ? RESIZE_FONT :
2172                         IsDlgButtonChecked(hwnd,
2173                                            IDC_RESIZEEITHER) ? RESIZE_EITHER :
2174                         RESIZE_DISABLED;
2175                 }
2176                 break;
2177               case IDC_WINEDIT:
2178                 if (HIWORD(wParam) == EN_CHANGE)
2179                     GetDlgItemText(hwnd, IDC_WINEDIT, cfg.wintitle,
2180                                    sizeof(cfg.wintitle) - 1);
2181                 break;
2182               case IDC_COEALWAYS:
2183               case IDC_COENEVER:
2184               case IDC_COENORMAL:
2185                 if (HIWORD(wParam) == BN_CLICKED ||
2186                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2187                     cfg.close_on_exit =
2188                         IsDlgButtonChecked(hwnd,
2189                                            IDC_COEALWAYS) ? COE_ALWAYS :
2190                         IsDlgButtonChecked(hwnd,
2191                                            IDC_COENEVER) ? COE_NEVER :
2192                         COE_NORMAL;
2193                 }
2194                 break;
2195               case IDC_CLOSEWARN:
2196                 if (HIWORD(wParam) == BN_CLICKED ||
2197                     HIWORD(wParam) == BN_DOUBLECLICKED)
2198                         cfg.warn_on_close =
2199                         IsDlgButtonChecked(hwnd, IDC_CLOSEWARN);
2200                 break;
2201               case IDC_TTEDIT:
2202                 if (HIWORD(wParam) == EN_CHANGE)
2203                     GetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype,
2204                                    sizeof(cfg.termtype) - 1);
2205                 break;
2206               case IDC_LGFEDIT:
2207                 if (HIWORD(wParam) == EN_CHANGE)
2208                     GetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename,
2209                                    sizeof(cfg.logfilename) - 1);
2210                 break;
2211               case IDC_LGFBUTTON:
2212                 memset(&of, 0, sizeof(of));
2213 #ifdef OPENFILENAME_SIZE_VERSION_400
2214                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2215 #else
2216                 of.lStructSize = sizeof(of);
2217 #endif
2218                 of.hwndOwner = hwnd;
2219                 of.lpstrFilter = "All Files\0*\0\0\0";
2220                 of.lpstrCustomFilter = NULL;
2221                 of.nFilterIndex = 1;
2222                 of.lpstrFile = filename;
2223                 strcpy(filename, cfg.logfilename);
2224                 of.nMaxFile = sizeof(filename);
2225                 of.lpstrFileTitle = NULL;
2226                 of.lpstrInitialDir = NULL;
2227                 of.lpstrTitle = "Select session log file";
2228                 of.Flags = 0;
2229                 if (GetSaveFileName(&of)) {
2230                     strcpy(cfg.logfilename, filename);
2231                     SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
2232                 }
2233                 break;
2234               case IDC_LSTATOFF:
2235               case IDC_LSTATASCII:
2236               case IDC_LSTATRAW:
2237                 if (HIWORD(wParam) == BN_CLICKED ||
2238                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2239                     if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF))
2240                         cfg.logtype = 0;
2241                     if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII))
2242                         cfg.logtype = 1;
2243                     if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW))
2244                         cfg.logtype = 2;
2245                 }
2246                 break;
2247               case IDC_LSTATXASK:
2248               case IDC_LSTATXAPN:
2249               case IDC_LSTATXOVR:
2250                 if (HIWORD(wParam) == BN_CLICKED ||
2251                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2252                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXASK))
2253                         cfg.logxfovr = LGXF_ASK;
2254                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXAPN))
2255                         cfg.logxfovr = LGXF_APN;
2256                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXOVR))
2257                         cfg.logxfovr = LGXF_OVR;
2258                 }
2259                 break;
2260               case IDC_TSEDIT:
2261               case IDC_R_TSEDIT:
2262                 if (HIWORD(wParam) == EN_CHANGE)
2263                     GetDlgItemText(hwnd, LOWORD(wParam), cfg.termspeed,
2264                                    sizeof(cfg.termspeed) - 1);
2265                 break;
2266               case IDC_LOGEDIT:
2267                 if (HIWORD(wParam) == EN_CHANGE)
2268                     GetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username,
2269                                    sizeof(cfg.username) - 1);
2270                 break;
2271               case IDC_RLLUSEREDIT:
2272                 if (HIWORD(wParam) == EN_CHANGE)
2273                     GetDlgItemText(hwnd, IDC_RLLUSEREDIT,
2274                                    cfg.localusername,
2275                                    sizeof(cfg.localusername) - 1);
2276                 break;
2277               case IDC_EMBSD:
2278               case IDC_EMRFC:
2279                 cfg.rfc_environ = IsDlgButtonChecked(hwnd, IDC_EMRFC);
2280                 break;
2281               case IDC_TPASSIVE:
2282               case IDC_TACTIVE:
2283                 cfg.passive_telnet =
2284                     IsDlgButtonChecked(hwnd, IDC_TPASSIVE);
2285                 break;
2286               case IDC_ENVADD:
2287                 if (HIWORD(wParam) == BN_CLICKED ||
2288                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2289                     char str[sizeof(cfg.environmt)];
2290                     char *p;
2291                     GetDlgItemText(hwnd, IDC_VAREDIT, str,
2292                                    sizeof(str) - 1);
2293                     if (!*str) {
2294                         MessageBeep(0);
2295                         break;
2296                     }
2297                     p = str + strlen(str);
2298                     *p++ = '\t';
2299                     GetDlgItemText(hwnd, IDC_VALEDIT, p,
2300                                    sizeof(str) - 1 - (p - str));
2301                     if (!*p) {
2302                         MessageBeep(0);
2303                         break;
2304                     }
2305                     p = cfg.environmt;
2306                     while (*p) {
2307                         while (*p)
2308                             p++;
2309                         p++;
2310                     }
2311                     if ((p - cfg.environmt) + strlen(str) + 2 <
2312                         sizeof(cfg.environmt)) {
2313                         strcpy(p, str);
2314                         p[strlen(str) + 1] = '\0';
2315                         SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_ADDSTRING,
2316                                            0, (LPARAM) str);
2317                         SetDlgItemText(hwnd, IDC_VAREDIT, "");
2318                         SetDlgItemText(hwnd, IDC_VALEDIT, "");
2319                     } else {
2320                         MessageBox(hwnd, "Environment too big",
2321                                    "PuTTY Error", MB_OK | MB_ICONERROR);
2322                     }
2323                 }
2324                 break;
2325               case IDC_ENVREMOVE:
2326                 if (HIWORD(wParam) != BN_CLICKED &&
2327                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
2328                 i =
2329                     SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_GETCURSEL, 0,
2330                                        0);
2331                 if (i == LB_ERR)
2332                     MessageBeep(0);
2333                 else {
2334                     char *p, *q;
2335
2336                     SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_DELETESTRING,
2337                                        i, 0);
2338                     p = cfg.environmt;
2339                     while (i > 0) {
2340                         if (!*p)
2341                             goto disaster;
2342                         while (*p)
2343                             p++;
2344                         p++;
2345                         i--;
2346                     }
2347                     q = p;
2348                     if (!*p)
2349                         goto disaster;
2350                     while (*p)
2351                         p++;
2352                     p++;
2353                     while (*p) {
2354                         while (*p)
2355                             *q++ = *p++;
2356                         *q++ = *p++;
2357                     }
2358                     *q = '\0';
2359                   disaster:;
2360                 }
2361                 break;
2362               case IDC_NOPTY:
2363                 if (HIWORD(wParam) == BN_CLICKED ||
2364                     HIWORD(wParam) == BN_DOUBLECLICKED)
2365                         cfg.nopty = IsDlgButtonChecked(hwnd, IDC_NOPTY);
2366                 break;
2367               case IDC_COMPRESS:
2368                 if (HIWORD(wParam) == BN_CLICKED ||
2369                     HIWORD(wParam) == BN_DOUBLECLICKED)
2370                         cfg.compression =
2371                         IsDlgButtonChecked(hwnd, IDC_COMPRESS);
2372                 break;
2373               case IDC_BUGGYMAC:
2374                 if (HIWORD(wParam) == BN_CLICKED ||
2375                     HIWORD(wParam) == BN_DOUBLECLICKED)
2376                         cfg.buggymac =
2377                         IsDlgButtonChecked(hwnd, IDC_BUGGYMAC);
2378                 break;
2379               case IDC_AGENTFWD:
2380                 if (HIWORD(wParam) == BN_CLICKED ||
2381                     HIWORD(wParam) == BN_DOUBLECLICKED)
2382                         cfg.agentfwd =
2383                         IsDlgButtonChecked(hwnd, IDC_AGENTFWD);
2384                 break;
2385               case IDC_CIPHERLIST:
2386               case IDC_CIPHERUP:
2387               case IDC_CIPHERDN:
2388                 handle_prefslist(&cipherlist,
2389                                  cfg.ssh_cipherlist, CIPHER_MAX,
2390                                  0, hwnd, wParam, lParam);
2391                 break;
2392               case IDC_SSHPROT1:
2393               case IDC_SSHPROT2:
2394                 if (HIWORD(wParam) == BN_CLICKED ||
2395                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2396                     if (IsDlgButtonChecked(hwnd, IDC_SSHPROT1))
2397                         cfg.sshprot = 1;
2398                     else if (IsDlgButtonChecked(hwnd, IDC_SSHPROT2))
2399                         cfg.sshprot = 2;
2400                 }
2401                 break;
2402               case IDC_AUTHTIS:
2403                 if (HIWORD(wParam) == BN_CLICKED ||
2404                     HIWORD(wParam) == BN_DOUBLECLICKED)
2405                         cfg.try_tis_auth =
2406                         IsDlgButtonChecked(hwnd, IDC_AUTHTIS);
2407                 break;
2408               case IDC_AUTHKI:
2409                 if (HIWORD(wParam) == BN_CLICKED ||
2410                     HIWORD(wParam) == BN_DOUBLECLICKED)
2411                         cfg.try_ki_auth =
2412                         IsDlgButtonChecked(hwnd, IDC_AUTHKI);
2413                 break;
2414               case IDC_PKEDIT:
2415                 if (HIWORD(wParam) == EN_CHANGE)
2416                     GetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile,
2417                                    sizeof(cfg.keyfile) - 1);
2418                 break;
2419               case IDC_CMDEDIT:
2420                 if (HIWORD(wParam) == EN_CHANGE)
2421                     GetDlgItemText(hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2422                                    sizeof(cfg.remote_cmd) - 1);
2423                 break;
2424               case IDC_PKBUTTON:
2425                 memset(&of, 0, sizeof(of));
2426 #ifdef OPENFILENAME_SIZE_VERSION_400
2427                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2428 #else
2429                 of.lStructSize = sizeof(of);
2430 #endif
2431                 of.hwndOwner = hwnd;
2432                 of.lpstrFilter = "All Files\0*\0\0\0";
2433                 of.lpstrCustomFilter = NULL;
2434                 of.nFilterIndex = 1;
2435                 of.lpstrFile = filename;
2436                 strcpy(filename, cfg.keyfile);
2437                 of.nMaxFile = sizeof(filename);
2438                 of.lpstrFileTitle = NULL;
2439                 of.lpstrInitialDir = NULL;
2440                 of.lpstrTitle = "Select Private Key File";
2441                 of.Flags = 0;
2442                 if (GetOpenFileName(&of)) {
2443                     strcpy(cfg.keyfile, filename);
2444                     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
2445                 }
2446                 break;
2447               case IDC_RAWCNP:
2448                 cfg.rawcnp = IsDlgButtonChecked(hwnd, IDC_RAWCNP);
2449                 break;
2450               case IDC_RTFPASTE:
2451                 cfg.rtf_paste = IsDlgButtonChecked(hwnd, IDC_RTFPASTE);
2452                 break;
2453               case IDC_MBWINDOWS:
2454               case IDC_MBXTERM:
2455                 cfg.mouse_is_xterm = IsDlgButtonChecked(hwnd, IDC_MBXTERM);
2456                 break;
2457               case IDC_SELTYPELEX:
2458               case IDC_SELTYPERECT:
2459                 cfg.rect_select = IsDlgButtonChecked(hwnd, IDC_SELTYPERECT);
2460                 break;
2461               case IDC_MOUSEOVERRIDE:
2462                 cfg.mouse_override = IsDlgButtonChecked(hwnd, IDC_MOUSEOVERRIDE);
2463                 break;
2464               case IDC_CCSET:
2465                 {
2466                     BOOL ok;
2467                     int i;
2468                     int n = GetDlgItemInt(hwnd, IDC_CCEDIT, &ok, FALSE);
2469
2470                     if (!ok)
2471                         MessageBeep(0);
2472                     else {
2473                         for (i = 0; i < 128; i++)
2474                             if (SendDlgItemMessage
2475                                 (hwnd, IDC_CCLIST, LB_GETSEL, i, 0)) {
2476                                 char str[100];
2477                                 cfg.wordness[i] = n;
2478                                 SendDlgItemMessage(hwnd, IDC_CCLIST,
2479                                                    LB_DELETESTRING, i, 0);
2480                                 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2481                                         (i >= 0x21 && i != 0x7F) ? i : ' ',
2482                                         cfg.wordness[i]);
2483                                 SendDlgItemMessage(hwnd, IDC_CCLIST,
2484                                                    LB_INSERTSTRING, i,
2485                                                    (LPARAM) str);
2486                             }
2487                     }
2488                 }
2489                 break;
2490               case IDC_BOLDCOLOUR:
2491                 if (HIWORD(wParam) == BN_CLICKED ||
2492                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2493                     int n, i;
2494                     cfg.bold_colour =
2495                         IsDlgButtonChecked(hwnd, IDC_BOLDCOLOUR);
2496                     SendDlgItemMessage(hwnd, IDC_COLOURLIST, WM_SETREDRAW,
2497                                        FALSE, 0);
2498                     n =
2499                         SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2500                                            LB_GETCOUNT, 0, 0);
2501                     if (n != 12 + 10 * cfg.bold_colour) {
2502                         for (i = n; i-- > 0;)
2503                             SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2504                                                LB_DELETESTRING, i, 0);
2505                         for (i = 0; i < 22; i++)
2506                             if (cfg.bold_colour || permcolour[i])
2507                                 SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2508                                                    LB_ADDSTRING, 0,
2509                                                    (LPARAM) colours[i]);
2510                     }
2511                     SendDlgItemMessage(hwnd, IDC_COLOURLIST, WM_SETREDRAW,
2512                                        TRUE, 0);
2513                     InvalidateRect(GetDlgItem(hwnd, IDC_COLOURLIST), NULL,
2514                                    TRUE);
2515                 }
2516                 break;
2517               case IDC_PALETTE:
2518                 if (HIWORD(wParam) == BN_CLICKED ||
2519                     HIWORD(wParam) == BN_DOUBLECLICKED)
2520                         cfg.try_palette =
2521                         IsDlgButtonChecked(hwnd, IDC_PALETTE);
2522                 break;
2523               case IDC_COLOURLIST:
2524                 if (HIWORD(wParam) == LBN_DBLCLK ||
2525                     HIWORD(wParam) == LBN_SELCHANGE) {
2526                     int i =
2527                         SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2528                                            LB_GETCURSEL,
2529                                            0, 0);
2530                     if (!cfg.bold_colour)
2531                         i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
2532                     SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
2533                                   FALSE);
2534                     SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[i][1],
2535                                   FALSE);
2536                     SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[i][2],
2537                                   FALSE);
2538                 }
2539                 break;
2540               case IDC_CHANGE:
2541                 if (HIWORD(wParam) == BN_CLICKED ||
2542                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2543                     static CHOOSECOLOR cc;
2544                     static DWORD custom[16] = { 0 };    /* zero initialisers */
2545                     int i =
2546                         SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2547                                            LB_GETCURSEL,
2548                                            0, 0);
2549                     if (!cfg.bold_colour)
2550                         i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
2551                     cc.lStructSize = sizeof(cc);
2552                     cc.hwndOwner = hwnd;
2553                     cc.hInstance = (HWND) hinst;
2554                     cc.lpCustColors = custom;
2555                     cc.rgbResult =
2556                         RGB(cfg.colours[i][0], cfg.colours[i][1],
2557                             cfg.colours[i][2]);
2558                     cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2559                     if (ChooseColor(&cc)) {
2560                         cfg.colours[i][0] =
2561                             (unsigned char) (cc.rgbResult & 0xFF);
2562                         cfg.colours[i][1] =
2563                             (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2564                         cfg.colours[i][2] =
2565                             (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2566                         SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
2567                                       FALSE);
2568                         SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[i][1],
2569                                       FALSE);
2570                         SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[i][2],
2571                                       FALSE);
2572                     }
2573                 }
2574                 break;
2575               case IDC_CODEPAGE:
2576                 if (HIWORD(wParam) == CBN_SELCHANGE) {
2577                     int index = SendDlgItemMessage(hwnd, IDC_CODEPAGE,
2578                                                    CB_GETCURSEL, 0, 0);
2579                     SendDlgItemMessage(hwnd, IDC_CODEPAGE, CB_GETLBTEXT,
2580                                        index, (LPARAM)cfg.line_codepage);
2581                 } else if (HIWORD(wParam) == CBN_EDITCHANGE) {
2582                     GetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage,
2583                                    sizeof(cfg.line_codepage) - 1);
2584                 } else if (HIWORD(wParam) == CBN_KILLFOCUS) {
2585                     strcpy(cfg.line_codepage,
2586                            cp_name(decode_codepage(cfg.line_codepage)));
2587                     SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
2588                 }
2589                 break;
2590               case IDC_CAPSLOCKCYR:
2591                 if (HIWORD(wParam) == BN_CLICKED ||
2592                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2593                     cfg.xlat_capslockcyr =
2594                         IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
2595                 }
2596                 break;
2597               case IDC_VTXWINDOWS:
2598               case IDC_VTOEMANSI:
2599               case IDC_VTOEMONLY:
2600               case IDC_VTPOORMAN:
2601               case IDC_VTUNICODE:
2602                 cfg.vtmode =
2603                     (IsDlgButtonChecked(hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS
2604                      : IsDlgButtonChecked(hwnd,
2605                                           IDC_VTOEMANSI) ? VT_OEMANSI :
2606                      IsDlgButtonChecked(hwnd,
2607                                         IDC_VTOEMONLY) ? VT_OEMONLY :
2608                      IsDlgButtonChecked(hwnd,
2609                                         IDC_VTUNICODE) ? VT_UNICODE :
2610                      VT_POORMAN);
2611                 break;
2612               case IDC_X11_FORWARD:
2613                 if (HIWORD(wParam) == BN_CLICKED ||
2614                     HIWORD(wParam) == BN_DOUBLECLICKED)
2615                         cfg.x11_forward =
2616                         IsDlgButtonChecked(hwnd, IDC_X11_FORWARD);
2617                 break;
2618               case IDC_LPORT_ALL:
2619                 if (HIWORD(wParam) == BN_CLICKED ||
2620                     HIWORD(wParam) == BN_DOUBLECLICKED)
2621                         cfg.lport_acceptall =
2622                         IsDlgButtonChecked(hwnd, IDC_LPORT_ALL);
2623                 break;
2624               case IDC_X11_DISPLAY:
2625                 if (HIWORD(wParam) == EN_CHANGE)
2626                     GetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display,
2627                                    sizeof(cfg.x11_display) - 1);
2628                 break;
2629               case IDC_PFWDADD:
2630                 if (HIWORD(wParam) == BN_CLICKED ||
2631                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2632                     char str[sizeof(cfg.portfwd)];
2633                     char *p;
2634                     if (IsDlgButtonChecked(hwnd, IDC_PFWDLOCAL))
2635                         str[0] = 'L';
2636                     else
2637                         str[0] = 'R';
2638                     GetDlgItemText(hwnd, IDC_SPORTEDIT, str+1,
2639                                    sizeof(str) - 2);
2640                     if (!str[1]) {
2641                         MessageBox(hwnd,
2642                                    "You need to specify a source port number",
2643                                    "PuTTY Error", MB_OK | MB_ICONERROR);
2644                         break;
2645                     }
2646                     p = str + strlen(str);
2647                     *p++ = '\t';
2648                     GetDlgItemText(hwnd, IDC_DPORTEDIT, p,
2649                                    sizeof(str) - 1 - (p - str));
2650                     if (!*p || !strchr(p, ':')) {
2651                         MessageBox(hwnd,
2652                                    "You need to specify a destination address\n"
2653                                    "in the form \"host.name:port\"",
2654                                    "PuTTY Error", MB_OK | MB_ICONERROR);
2655                         break;
2656                     }
2657                     p = cfg.portfwd;
2658                     while (*p) {
2659                         while (*p)
2660                             p++;
2661                         p++;
2662                     }
2663                     if ((p - cfg.portfwd) + strlen(str) + 2 <
2664                         sizeof(cfg.portfwd)) {
2665                         strcpy(p, str);
2666                         p[strlen(str) + 1] = '\0';
2667                         SendDlgItemMessage(hwnd, IDC_PFWDLIST, LB_ADDSTRING,
2668                                            0, (LPARAM) str);
2669                         SetDlgItemText(hwnd, IDC_SPORTEDIT, "");
2670                         SetDlgItemText(hwnd, IDC_DPORTEDIT, "");
2671                     } else {
2672                         MessageBox(hwnd, "Too many forwardings",
2673                                    "PuTTY Error", MB_OK | MB_ICONERROR);
2674                     }
2675                 }
2676                 break;
2677               case IDC_PFWDREMOVE:
2678                 if (HIWORD(wParam) != BN_CLICKED &&
2679                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
2680                 i = SendDlgItemMessage(hwnd, IDC_PFWDLIST,
2681                                        LB_GETCURSEL, 0, 0);
2682                 if (i == LB_ERR)
2683                     MessageBeep(0);
2684                 else {
2685                     char *p, *q;
2686
2687                     SendDlgItemMessage(hwnd, IDC_PFWDLIST, LB_DELETESTRING,
2688                                        i, 0);
2689                     p = cfg.portfwd;
2690                     while (i > 0) {
2691                         if (!*p)
2692                             goto disaster2;
2693                         while (*p)
2694                             p++;
2695                         p++;
2696                         i--;
2697                     }
2698                     q = p;
2699                     if (!*p)
2700                         goto disaster2;
2701                     while (*p)
2702                         p++;
2703                     p++;
2704                     while (*p) {
2705                         while (*p)
2706                             *q++ = *p++;
2707                         *q++ = *p++;
2708                     }
2709                     *q = '\0';
2710                   disaster2:;
2711                 }
2712                 break;
2713             }
2714         return 0;
2715       case WM_CLOSE:
2716         EndDialog(hwnd, 0);
2717         return 0;
2718
2719         /* Grrr Explorer will maximize Dialogs! */
2720       case WM_SIZE:
2721         if (wParam == SIZE_MAXIMIZED)
2722             force_normal(hwnd);
2723         return 0;
2724
2725       default:
2726         /*
2727          * Handle application-defined messages eg. DragListBox
2728          */
2729         /* First find out what the number is (once). */
2730         if (draglistmsg == WM_NULL)
2731             draglistmsg = RegisterWindowMessage (DRAGLISTMSGSTRING);
2732
2733         if (msg == draglistmsg) {
2734             /* Only process once dialog is fully formed. */
2735             if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
2736               case IDC_CIPHERLIST:
2737                 return handle_prefslist(&cipherlist,
2738                                         cfg.ssh_cipherlist, CIPHER_MAX,
2739                                         1, hwnd, wParam, lParam);
2740             }
2741         }
2742         return 0;
2743
2744     }
2745     return 0;
2746 }
2747
2748 static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
2749                                 WPARAM wParam, LPARAM lParam)
2750 {
2751     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2752     }
2753     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2754         EnableWindow(hwnd, 0);
2755         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
2756         EnableWindow(hwnd, 1);
2757         SetActiveWindow(hwnd);
2758     }
2759     return GenericMainDlgProc(hwnd, msg, wParam, lParam, 0);
2760 }
2761
2762 static int CALLBACK ReconfDlgProc(HWND hwnd, UINT msg,
2763                                   WPARAM wParam, LPARAM lParam)
2764 {
2765     return GenericMainDlgProc(hwnd, msg, wParam, lParam, 1);
2766 }
2767
2768 void defuse_showwindow(void)
2769 {
2770     /*
2771      * Work around the fact that the app's first call to ShowWindow
2772      * will ignore the default in favour of the shell-provided
2773      * setting.
2774      */
2775     {
2776         HWND hwnd;
2777         hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2778                             NULL, NullDlgProc);
2779         ShowWindow(hwnd, SW_HIDE);
2780         SetActiveWindow(hwnd);
2781         DestroyWindow(hwnd);
2782     }
2783 }
2784
2785 int do_config(void)
2786 {
2787     int ret;
2788
2789     get_sesslist(TRUE);
2790     savedsession[0] = '\0';
2791     ret =
2792         DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2793     get_sesslist(FALSE);
2794
2795     return ret;
2796 }
2797
2798 int do_reconfig(HWND hwnd)
2799 {
2800     Config backup_cfg;
2801     int ret;
2802
2803     backup_cfg = cfg;                  /* structure copy */
2804     ret =
2805         DialogBox(hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2806     if (!ret)
2807         cfg = backup_cfg;              /* structure copy */
2808
2809     return ret;
2810 }
2811
2812 void logevent(char *string)
2813 {
2814     char timebuf[40];
2815     time_t t;
2816
2817     if (nevents >= negsize) {
2818         negsize += 64;
2819         events = srealloc(events, negsize * sizeof(*events));
2820     }
2821
2822     time(&t);
2823     strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t",
2824              localtime(&t));
2825
2826     events[nevents] = smalloc(strlen(timebuf) + strlen(string) + 1);
2827     strcpy(events[nevents], timebuf);
2828     strcat(events[nevents], string);
2829     if (logbox) {
2830         int count;
2831         SendDlgItemMessage(logbox, IDN_LIST, LB_ADDSTRING,
2832                            0, (LPARAM) events[nevents]);
2833         count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2834         SendDlgItemMessage(logbox, IDN_LIST, LB_SETTOPINDEX, count - 1, 0);
2835     }
2836     nevents++;
2837 }
2838
2839 void showeventlog(HWND hwnd)
2840 {
2841     if (!logbox) {
2842         logbox = CreateDialog(hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2843                               hwnd, LogProc);
2844         ShowWindow(logbox, SW_SHOWNORMAL);
2845     }
2846     SetActiveWindow(logbox);
2847 }
2848
2849 void showabout(HWND hwnd)
2850 {
2851     DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
2852 }
2853
2854 void verify_ssh_host_key(char *host, int port, char *keytype,
2855                          char *keystr, char *fingerprint)
2856 {
2857     int ret;
2858
2859     static const char absentmsg[] =
2860         "The server's host key is not cached in the registry. You\n"
2861         "have no guarantee that the server is the computer you\n"
2862         "think it is.\n"
2863         "The server's key fingerprint is:\n"
2864         "%s\n"
2865         "If you trust this host, hit Yes to add the key to\n"
2866         "PuTTY's cache and carry on connecting.\n"
2867         "If you want to carry on connecting just once, without\n"
2868         "adding the key to the cache, hit No.\n"
2869         "If you do not trust this host, hit Cancel to abandon the\n"
2870         "connection.\n";
2871
2872     static const char wrongmsg[] =
2873         "WARNING - POTENTIAL SECURITY BREACH!\n"
2874         "\n"
2875         "The server's host key does not match the one PuTTY has\n"
2876         "cached in the registry. This means that either the\n"
2877         "server administrator has changed the host key, or you\n"
2878         "have actually connected to another computer pretending\n"
2879         "to be the server.\n"
2880         "The new key fingerprint is:\n"
2881         "%s\n"
2882         "If you were expecting this change and trust the new key,\n"
2883         "hit Yes to update PuTTY's cache and continue connecting.\n"
2884         "If you want to carry on connecting but without updating\n"
2885         "the cache, hit No.\n"
2886         "If you want to abandon the connection completely, hit\n"
2887         "Cancel. Hitting Cancel is the ONLY guaranteed safe\n" "choice.\n";
2888
2889     static const char mbtitle[] = "PuTTY Security Alert";
2890
2891     char message[160 +
2892         /* sensible fingerprint max size */
2893         (sizeof(absentmsg) > sizeof(wrongmsg) ?
2894          sizeof(absentmsg) : sizeof(wrongmsg))];
2895
2896     /*
2897      * Verify the key against the registry.
2898      */
2899     ret = verify_host_key(host, port, keytype, keystr);
2900
2901     if (ret == 0)                      /* success - key matched OK */
2902         return;
2903     if (ret == 2) {                    /* key was different */
2904         int mbret;
2905         sprintf(message, wrongmsg, fingerprint);
2906         mbret = MessageBox(NULL, message, mbtitle,
2907                            MB_ICONWARNING | MB_YESNOCANCEL);
2908         if (mbret == IDYES)
2909             store_host_key(host, port, keytype, keystr);
2910         if (mbret == IDCANCEL)
2911             exit(0);
2912     }
2913     if (ret == 1) {                    /* key was absent */
2914         int mbret;
2915         sprintf(message, absentmsg, fingerprint);
2916         mbret = MessageBox(NULL, message, mbtitle,
2917                            MB_ICONWARNING | MB_YESNOCANCEL);
2918         if (mbret == IDYES)
2919             store_host_key(host, port, keytype, keystr);
2920         if (mbret == IDCANCEL)
2921             exit(0);
2922     }
2923 }
2924
2925 /*
2926  * Ask whether the selected cipher is acceptable (since it was
2927  * below the configured 'warn' threshold).
2928  * cs: 0 = both ways, 1 = client->server, 2 = server->client
2929  */
2930 void askcipher(char *ciphername, int cs)
2931 {
2932     static const char mbtitle[] = "PuTTY Security Alert";
2933     static const char msg[] =
2934         "The first %.35scipher supported by the server\n"
2935         "is %.64s, which is below the configured\n"
2936         "warning threshold.\n"
2937         "Do you want to continue with this connection?\n";
2938     /* guessed cipher name + type max length */
2939     char message[100 + sizeof(msg)];
2940     int mbret;
2941
2942     sprintf(message, msg,
2943             (cs == 0) ? "" :
2944             (cs == 1) ? "client-to-server " :
2945                         "server-to-client ",
2946             ciphername);
2947     mbret = MessageBox(NULL, message, mbtitle,
2948                        MB_ICONWARNING | MB_YESNO);
2949     if (mbret == IDYES)
2950         return;
2951     else
2952         exit(0);
2953 }
2954
2955 /*
2956  * Ask whether to wipe a session log file before writing to it.
2957  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2958  */
2959 int askappend(char *filename)
2960 {
2961     static const char mbtitle[] = "PuTTY Log to File";
2962     static const char msgtemplate[] =
2963         "The session log file \"%.*s\" already exists.\n"
2964         "You can overwrite it with a new session log,\n"
2965         "append your session log to the end of it,\n"
2966         "or disable session logging for this session.\n"
2967         "Hit Yes to wipe the file, No to append to it,\n"
2968         "or Cancel to disable logging.";
2969     char message[sizeof(msgtemplate) + FILENAME_MAX];
2970     int mbret;
2971     if (cfg.logxfovr != LGXF_ASK) {
2972         return ((cfg.logxfovr == LGXF_OVR) ? 2 : 1);
2973     }
2974     sprintf(message, msgtemplate, FILENAME_MAX, filename);
2975
2976     mbret = MessageBox(NULL, message, mbtitle,
2977                        MB_ICONQUESTION | MB_YESNOCANCEL);
2978     if (mbret == IDYES)
2979         return 2;
2980     else if (mbret == IDNO)
2981         return 1;
2982     else
2983         return 0;
2984 }
2985
2986 /*
2987  * Warn about the obsolescent key file format.
2988  */
2989 void old_keyfile_warning(void)
2990 {
2991     static const char mbtitle[] = "PuTTY Key File Warning";
2992     static const char message[] =
2993         "You are loading an SSH 2 private key which has an\n"
2994         "old version of the file format. This means your key\n"
2995         "file is not fully tamperproof. Future versions of\n"
2996         "PuTTY may stop supporting this private key format,\n"
2997         "so we recommend you convert your key to the new\n"
2998         "format.\n"
2999         "\n"
3000         "You can perform this conversion by loading the key\n"
3001         "into PuTTYgen and then saving it again.";
3002
3003     MessageBox(NULL, message, mbtitle, MB_OK);
3004 }