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