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