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