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