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