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