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