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