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