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