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