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