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