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