]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
Added a new large icon for the PuTTY config box. Doesn't show up in
[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_aclip(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     IDC_TELNETKEY,
295     keyboardpanelend,
296
297     terminalpanelstart,
298     IDC_TITLE_TERMINAL,
299     IDC_BOX_TERMINAL1,
300     IDC_BOX_TERMINAL2,
301     IDC_WRAPMODE,
302     IDC_DECOM,
303     IDC_LFHASCR,
304     IDC_BCE,
305     IDC_BLINKTEXT,
306     IDC_ANSWERBACK,
307     IDC_ANSWEREDIT,
308     IDC_ECHOSTATIC,
309     IDC_ECHOBACKEND,
310     IDC_ECHOYES,
311     IDC_ECHONO,
312     IDC_EDITSTATIC,
313     IDC_EDITBACKEND,
314     IDC_EDITYES,
315     IDC_EDITNO,
316     terminalpanelend,
317
318     bellpanelstart,
319     IDC_TITLE_BELL,
320     IDC_BOX_BELL1,
321     IDC_BOX_BELL2,
322     IDC_BELLSTATIC,
323     IDC_BELL_DISABLED,
324     IDC_BELL_DEFAULT,
325     IDC_BELL_WAVEFILE,
326     IDC_BELL_VISUAL,
327     IDC_BELL_WAVESTATIC,
328     IDC_BELL_WAVEEDIT,
329     IDC_BELL_WAVEBROWSE,
330     IDC_BELLOVL,
331     IDC_BELLOVLNSTATIC,
332     IDC_BELLOVLN,
333     IDC_BELLOVLTSTATIC,
334     IDC_BELLOVLT,
335     IDC_BELLOVLEXPLAIN,
336     IDC_BELLOVLSSTATIC,
337     IDC_BELLOVLS,
338     bellpanelend,
339
340     windowpanelstart,
341     IDC_TITLE_WINDOW,
342     IDC_BOX_WINDOW1,
343     IDC_BOX_WINDOW2,
344     IDC_BOX_WINDOW3,
345     IDC_ROWSSTATIC,
346     IDC_ROWSEDIT,
347     IDC_COLSSTATIC,
348     IDC_COLSEDIT,
349     IDC_LOCKSIZE,
350     IDC_SCROLLBAR,
351     IDC_CLOSEWARN,
352     IDC_SAVESTATIC,
353     IDC_SAVEEDIT,
354     IDC_ALTF4,
355     IDC_ALTSPACE,
356     IDC_ALTONLY,
357     IDC_SCROLLKEY,
358     IDC_SCROLLDISP,
359     IDC_ALWAYSONTOP,
360     windowpanelend,
361
362     appearancepanelstart,
363     IDC_TITLE_APPEARANCE,
364     IDC_BOX_APPEARANCE1,
365     IDC_BOX_APPEARANCE2,
366     IDC_BOX_APPEARANCE3,
367     IDC_BOX_APPEARANCE4,
368     IDC_BOX_APPEARANCE5,
369     IDC_CURSORSTATIC,
370     IDC_CURBLOCK,
371     IDC_CURUNDER,
372     IDC_CURVERT,
373     IDC_BLINKCUR,
374     IDC_FONTSTATIC,
375     IDC_CHOOSEFONT,
376     IDC_WINTITLE,
377     IDC_WINEDIT,
378     IDC_WINNAME,
379     IDC_HIDEMOUSE,
380     IDC_SUNKENEDGE,
381     appearancepanelend,
382
383     connectionpanelstart,
384     IDC_TITLE_CONNECTION,
385     IDC_BOX_CONNECTION1,
386     IDC_BOX_CONNECTION2,
387     IDC_TTSTATIC,
388     IDC_TTEDIT,
389     IDC_LOGSTATIC,
390     IDC_LOGEDIT,
391     IDC_PINGSTATIC,
392     IDC_PINGEDIT,
393     connectionpanelend,
394
395     telnetpanelstart,
396     IDC_TITLE_TELNET,
397     IDC_BOX_TELNET1,
398     IDC_BOX_TELNET2,
399     IDC_TSSTATIC,
400     IDC_TSEDIT,
401     IDC_ENVSTATIC,
402     IDC_VARSTATIC,
403     IDC_VAREDIT,
404     IDC_VALSTATIC,
405     IDC_VALEDIT,
406     IDC_ENVLIST,
407     IDC_ENVADD,
408     IDC_ENVREMOVE,
409     IDC_EMSTATIC,
410     IDC_EMBSD,
411     IDC_EMRFC,
412     IDC_ACTSTATIC,
413     IDC_TPASSIVE,
414     IDC_TACTIVE,
415     telnetpanelend,
416
417     rloginpanelstart,
418     IDC_TITLE_RLOGIN,
419     IDC_BOX_RLOGIN1,
420     IDC_BOX_RLOGIN2,
421     IDC_R_TSSTATIC,
422     IDC_R_TSEDIT,
423     IDC_RLLUSERSTATIC,
424     IDC_RLLUSEREDIT,
425     rloginpanelend,
426
427     sshpanelstart,
428     IDC_TITLE_SSH,
429     IDC_BOX_SSH1,
430     IDC_BOX_SSH2,
431     IDC_BOX_SSH3,
432     IDC_NOPTY,
433     IDC_CIPHERSTATIC,
434     IDC_CIPHER3DES,
435     IDC_CIPHERBLOWF,
436     IDC_CIPHERDES,
437     IDC_CIPHERAES,
438     IDC_BUGGYMAC,
439     IDC_AUTHTIS,
440     IDC_PKSTATIC,
441     IDC_PKEDIT,
442     IDC_PKBUTTON,
443     IDC_SSHPROTSTATIC,
444     IDC_SSHPROT1,
445     IDC_SSHPROT2,
446     IDC_AGENTFWD,
447     IDC_CMDSTATIC,
448     IDC_CMDEDIT,
449     IDC_COMPRESS,
450     sshpanelend,
451
452     selectionpanelstart,
453     IDC_TITLE_SELECTION,
454     IDC_BOX_SELECTION1,
455     IDC_BOX_SELECTION2,
456     IDC_BOX_SELECTION3,
457     IDC_MBSTATIC,
458     IDC_MBWINDOWS,
459     IDC_MBXTERM,
460     IDC_CCSTATIC,
461     IDC_CCLIST,
462     IDC_CCSET,
463     IDC_CCSTATIC2,
464     IDC_CCEDIT,
465     IDC_RAWCNP,
466     selectionpanelend,
467
468     colourspanelstart,
469     IDC_TITLE_COLOURS,
470     IDC_BOX_COLOURS1,
471     IDC_BOX_COLOURS2,
472     IDC_BOLDCOLOUR,
473     IDC_PALETTE,
474     IDC_COLOURSTATIC,
475     IDC_COLOURLIST,
476     IDC_RSTATIC,
477     IDC_GSTATIC,
478     IDC_BSTATIC,
479     IDC_RVALUE,
480     IDC_GVALUE,
481     IDC_BVALUE,
482     IDC_CHANGE,
483     colourspanelend,
484
485     translationpanelstart,
486     IDC_TITLE_TRANSLATION,
487     IDC_BOX_TRANSLATION1,
488     IDC_BOX_TRANSLATION2,
489     IDC_CODEPAGESTATIC,
490     IDC_CODEPAGE,
491     IDC_VTSTATIC,
492     IDC_VTXWINDOWS,
493     IDC_VTOEMANSI,
494     IDC_VTOEMONLY,
495     IDC_VTPOORMAN,
496     IDC_VTUNICODE,
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     CheckDlgButton(hwnd, IDC_TELNETKEY, cfg.telnet_keyboard);
589     CheckRadioButton(hwnd, IDC_ECHOBACKEND, IDC_ECHONO,
590                      cfg.localecho == LD_BACKEND ? IDC_ECHOBACKEND :
591                      cfg.localecho == LD_YES ? IDC_ECHOYES : IDC_ECHONO);
592     CheckRadioButton(hwnd, IDC_EDITBACKEND, IDC_EDITNO,
593                      cfg.localedit == LD_BACKEND ? IDC_EDITBACKEND :
594                      cfg.localedit == LD_YES ? IDC_EDITYES : IDC_EDITNO);
595     SetDlgItemText(hwnd, IDC_ANSWEREDIT, cfg.answerback);
596     CheckDlgButton(hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
597     CheckDlgButton(hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
598     CheckDlgButton(hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
599
600     CheckDlgButton(hwnd, IDC_WRAPMODE, cfg.wrap_mode);
601     CheckDlgButton(hwnd, IDC_DECOM, cfg.dec_om);
602     CheckDlgButton(hwnd, IDC_LFHASCR, cfg.lfhascr);
603     SetDlgItemInt(hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
604     SetDlgItemInt(hwnd, IDC_COLSEDIT, cfg.width, FALSE);
605     SetDlgItemInt(hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
606     fmtfont(fontstatic);
607     SetDlgItemText(hwnd, IDC_FONTSTATIC, fontstatic);
608     CheckRadioButton(hwnd, IDC_BELL_DISABLED, IDC_BELL_VISUAL,
609                      cfg.beep == BELL_DISABLED ? IDC_BELL_DISABLED :
610                      cfg.beep == BELL_DEFAULT ? IDC_BELL_DEFAULT :
611                      cfg.beep == BELL_WAVEFILE ? IDC_BELL_WAVEFILE :
612                      cfg.beep ==
613                      BELL_VISUAL ? IDC_BELL_VISUAL : IDC_BELL_DEFAULT);
614     SetDlgItemText(hwnd, IDC_BELL_WAVEEDIT, cfg.bell_wavefile);
615     CheckDlgButton(hwnd, IDC_BELLOVL, cfg.bellovl);
616     SetDlgItemInt(hwnd, IDC_BELLOVLN, cfg.bellovl_n, FALSE);
617     MySetDlgItemFlt(hwnd, IDC_BELLOVLT, cfg.bellovl_t / 1000.0);
618     MySetDlgItemFlt(hwnd, IDC_BELLOVLS, cfg.bellovl_s / 1000.0);
619
620     CheckDlgButton(hwnd, IDC_BCE, cfg.bce);
621     CheckDlgButton(hwnd, IDC_BLINKTEXT, cfg.blinktext);
622
623     SetDlgItemText(hwnd, IDC_WINEDIT, cfg.wintitle);
624     CheckDlgButton(hwnd, IDC_WINNAME, cfg.win_name_always);
625     CheckDlgButton(hwnd, IDC_HIDEMOUSE, cfg.hide_mouseptr);
626     CheckDlgButton(hwnd, IDC_SUNKENEDGE, cfg.sunken_edge);
627     CheckRadioButton(hwnd, IDC_CURBLOCK, IDC_CURVERT,
628                      cfg.cursor_type == 0 ? IDC_CURBLOCK :
629                      cfg.cursor_type == 1 ? IDC_CURUNDER : IDC_CURVERT);
630     CheckDlgButton(hwnd, IDC_BLINKCUR, cfg.blink_cur);
631     CheckDlgButton(hwnd, IDC_SCROLLBAR, cfg.scrollbar);
632     CheckDlgButton(hwnd, IDC_LOCKSIZE, cfg.locksize);
633     CheckRadioButton(hwnd, IDC_COEALWAYS, IDC_COENORMAL,
634                      cfg.close_on_exit == COE_NORMAL ? IDC_COENORMAL :
635                      cfg.close_on_exit ==
636                      COE_NEVER ? IDC_COENEVER : IDC_COEALWAYS);
637     CheckDlgButton(hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
638
639     SetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype);
640     SetDlgItemText(hwnd, IDC_TSEDIT, cfg.termspeed);
641     SetDlgItemText(hwnd, IDC_R_TSEDIT, cfg.termspeed);
642     SetDlgItemText(hwnd, IDC_RLLUSEREDIT, cfg.localusername);
643     SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
644     SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
645     CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
646                      cfg.logtype == 0 ? IDC_LSTATOFF :
647                      cfg.logtype == 1 ? IDC_LSTATASCII : IDC_LSTATRAW);
648     CheckRadioButton(hwnd, IDC_LSTATXOVR, IDC_LSTATXASK,
649                      cfg.logxfovr == LGXF_OVR ? IDC_LSTATXOVR :
650                      cfg.logxfovr == LGXF_ASK ? IDC_LSTATXASK :
651                      IDC_LSTATXAPN);
652     {
653         char *p = cfg.environmt;
654         while (*p) {
655             SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
656                                (LPARAM) p);
657             p += strlen(p) + 1;
658         }
659     }
660     CheckRadioButton(hwnd, IDC_EMBSD, IDC_EMRFC,
661                      cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
662     CheckRadioButton(hwnd, IDC_TPASSIVE, IDC_TACTIVE,
663                      cfg.passive_telnet ? IDC_TPASSIVE : IDC_TACTIVE);
664
665     SetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype);
666     SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
667     CheckDlgButton(hwnd, IDC_NOPTY, cfg.nopty);
668     CheckDlgButton(hwnd, IDC_COMPRESS, cfg.compression);
669     CheckDlgButton(hwnd, IDC_BUGGYMAC, cfg.buggymac);
670     CheckDlgButton(hwnd, IDC_AGENTFWD, cfg.agentfwd);
671     CheckRadioButton(hwnd, IDC_CIPHER3DES, IDC_CIPHERAES,
672                      cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
673                      cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
674                      cfg.cipher == CIPHER_AES ? IDC_CIPHERAES :
675                      IDC_CIPHER3DES);
676     CheckRadioButton(hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
677                      cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
678     CheckDlgButton(hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
679     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
680     SetDlgItemText(hwnd, IDC_CMDEDIT, cfg.remote_cmd);
681
682     CheckRadioButton(hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
683                      cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
684     CheckDlgButton(hwnd, IDC_RAWCNP, cfg.rawcnp);
685     {
686         static int tabs[4] = { 25, 61, 96, 128 };
687         SendDlgItemMessage(hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
688                            (LPARAM) tabs);
689     }
690     for (i = 0; i < 128; i++) {
691         char str[100];
692         sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
693                 (i >= 0x21 && i != 0x7F) ? i : ' ', cfg.wordness[i]);
694         SendDlgItemMessage(hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
695                            (LPARAM) str);
696     }
697
698     CheckDlgButton(hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
699     CheckDlgButton(hwnd, IDC_PALETTE, cfg.try_palette);
700     {
701         int i, n;
702         n = SendDlgItemMessage(hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
703         for (i = n; i-- > 0;)
704             SendDlgItemMessage(hwnd, IDC_COLOURLIST,
705                                LB_DELETESTRING, i, 0);
706         for (i = 0; i < 22; i++)
707             if (cfg.bold_colour || permcolour[i])
708                 SendDlgItemMessage(hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
709                                    (LPARAM) colours[i]);
710     }
711     SendDlgItemMessage(hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
712     SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
713     SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
714     SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
715
716     SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
717     CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTUNICODE,
718                      cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
719                      cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
720                      cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
721                      cfg.vtmode == VT_UNICODE ? IDC_VTUNICODE :
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, 3,
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, "&Unicode mode", IDC_VTUNICODE, NULL);
1015         endbox(&cp);
1016         beginbox(&cp, "Enable character set translation on received data",
1017                  IDC_BOX_TRANSLATION2);
1018         multiedit(&cp, "Line codepage:", IDC_CODEPAGESTATIC,
1019                   IDC_CODEPAGE, 100, NULL);
1020         endbox(&cp);
1021     }
1022
1023     if (panel == selectionpanelstart) {
1024         /* The Selection panel. Accelerators used: [acgo] d wx hst */
1025         struct ctlpos cp;
1026         ctlposinit(&cp, hwnd, 80, 3, 13);
1027         bartitle(&cp, "Options controlling copy and paste",
1028                  IDC_TITLE_SELECTION);
1029         beginbox(&cp, "Translation of pasted characters",
1030                  IDC_BOX_SELECTION1);
1031         checkbox(&cp,
1032                  "&Don't translate line drawing chars into +, - and |",
1033                  IDC_RAWCNP);
1034         endbox(&cp);
1035         beginbox(&cp, "Control which mouse button does which thing",
1036                  IDC_BOX_SELECTION2);
1037         radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1038                  "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1039                  "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1040                  NULL);
1041         endbox(&cp);
1042         beginbox(&cp, "Control the select-one-word-at-a-time mode",
1043                  IDC_BOX_SELECTION3);
1044         charclass(&cp, "C&haracter classes:", IDC_CCSTATIC, IDC_CCLIST,
1045                   "&Set", IDC_CCSET, IDC_CCEDIT,
1046                   "&to class", IDC_CCSTATIC2);
1047         endbox(&cp);
1048     }
1049
1050     if (panel == colourspanelstart) {
1051         /* The Colours panel. Accelerators used: [acgo] blum */
1052         struct ctlpos cp;
1053         ctlposinit(&cp, hwnd, 80, 3, 13);
1054         bartitle(&cp, "Options controlling use of colours",
1055                  IDC_TITLE_COLOURS);
1056         beginbox(&cp, "General options for colour usage",
1057                  IDC_BOX_COLOURS1);
1058         checkbox(&cp, "&Bolded text is a different colour",
1059                  IDC_BOLDCOLOUR);
1060         checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1061         endbox(&cp);
1062         beginbox(&cp, "Adjust the precise colours PuTTY displays",
1063                  IDC_BOX_COLOURS2);
1064         colouredit(&cp, "Select a colo&ur and then click to modify it:",
1065                    IDC_COLOURSTATIC, IDC_COLOURLIST,
1066                    "&Modify...", IDC_CHANGE,
1067                    "Red:", IDC_RSTATIC, IDC_RVALUE,
1068                    "Green:", IDC_GSTATIC, IDC_GVALUE,
1069                    "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1070         endbox(&cp);
1071     }
1072
1073     if (panel == connectionpanelstart) {
1074         /* The Connection panel. Accelerators used: [acgo] tuk */
1075         struct ctlpos cp;
1076         ctlposinit(&cp, hwnd, 80, 3, 13);
1077         bartitle(&cp, "Options controlling the connection",
1078                  IDC_TITLE_CONNECTION);
1079         if (dlgtype == 0) {
1080             beginbox(&cp, "Data to send to the server",
1081                      IDC_BOX_CONNECTION1);
1082             staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC,
1083                        IDC_TTEDIT, 50);
1084             staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC,
1085                        IDC_LOGEDIT, 50);
1086             endbox(&cp);
1087         } else {
1088             beginbox(&cp, "Adjust telnet session.", IDC_BOX_CONNECTION1);
1089             checkbox(&cp, "Keyboard sends telnet Backspace and Interrupt",
1090                      IDC_TELNETKEY);
1091             endbox(&cp);
1092         }
1093         beginbox(&cp, "Sending of null packets to keep session active",
1094                  IDC_BOX_CONNECTION2);
1095         staticedit(&cp, "Seconds between &keepalives (0 to turn off)",
1096                    IDC_PINGSTATIC, IDC_PINGEDIT, 20);
1097         endbox(&cp);
1098     }
1099
1100     if (panel == telnetpanelstart) {
1101         /* The Telnet panel. Accelerators used: [acgo] svldr bftk */
1102         struct ctlpos cp;
1103         ctlposinit(&cp, hwnd, 80, 3, 13);
1104         if (dlgtype == 0) {
1105             bartitle(&cp, "Options controlling Telnet connections",
1106                      IDC_TITLE_TELNET);
1107             beginbox(&cp, "Data to send to the server", IDC_BOX_TELNET1);
1108             staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC,
1109                        IDC_TSEDIT, 50);
1110             envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1111                       "&Variable", IDC_VARSTATIC, IDC_VAREDIT, "Va&lue",
1112                       IDC_VALSTATIC, IDC_VALEDIT, IDC_ENVLIST, "A&dd",
1113                       IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1114             endbox(&cp);
1115             beginbox(&cp, "Telnet protocol adjustments", IDC_BOX_TELNET2);
1116             radioline(&cp, "Handling of OLD_ENVIRON ambiguity:",
1117                       IDC_EMSTATIC, 2, "&BSD (commonplace)", IDC_EMBSD,
1118                       "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1119             radioline(&cp, "&Telnet negotiation mode:", IDC_ACTSTATIC, 2,
1120                       "Passive", IDC_TPASSIVE, "Active",
1121                       IDC_TACTIVE, NULL);
1122             checkbox(&cp, "&Keyboard sends telnet Backspace and Interrupt",
1123                      IDC_TELNETKEY);
1124             endbox(&cp);
1125         }
1126     }
1127
1128     if (panel == rloginpanelstart) {
1129         /* The Rlogin panel. Accelerators used: [acgo] sl */
1130         struct ctlpos cp;
1131         ctlposinit(&cp, hwnd, 80, 3, 13);
1132         if (dlgtype == 0) {
1133             bartitle(&cp, "Options controlling Rlogin connections",
1134                      IDC_TITLE_RLOGIN);
1135             beginbox(&cp, "Data to send to the server", IDC_BOX_RLOGIN1);
1136             staticedit(&cp, "Terminal-&speed string", IDC_R_TSSTATIC,
1137                        IDC_R_TSEDIT, 50);
1138             staticedit(&cp, "&Local username:", IDC_RLLUSERSTATIC,
1139                        IDC_RLLUSEREDIT, 50);
1140             endbox(&cp);
1141         }
1142     }
1143
1144     if (panel == sshpanelstart) {
1145         /* The SSH panel. Accelerators used: [acgo] rmfkw pe123bds i */
1146         struct ctlpos cp;
1147         ctlposinit(&cp, hwnd, 80, 3, 13);
1148         if (dlgtype == 0) {
1149             bartitle(&cp, "Options controlling SSH connections",
1150                      IDC_TITLE_SSH);
1151             beginbox(&cp, "Data to send to the server", IDC_BOX_SSH1);
1152             multiedit(&cp,
1153                       "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1154                       NULL);
1155             endbox(&cp);
1156             beginbox(&cp, "Authentication options", IDC_BOX_SSH2);
1157             checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1158                      IDC_AUTHTIS);
1159             checkbox(&cp, "Allow agent &forwarding", IDC_AGENTFWD);
1160             editbutton(&cp, "Private &key file for authentication:",
1161                        IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...",
1162                        IDC_PKBUTTON);
1163             endbox(&cp);
1164             beginbox(&cp, "Protocol options", IDC_BOX_SSH3);
1165             checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1166             checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
1167             radioline(&cp, "Preferred SSH protocol version:",
1168                       IDC_SSHPROTSTATIC, 2,
1169                       "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1170             radioline(&cp, "Preferred encryption algorithm:",
1171                       IDC_CIPHERSTATIC, 4, "&3DES", IDC_CIPHER3DES,
1172                       "&Blowfish", IDC_CIPHERBLOWF, "&DES", IDC_CIPHERDES,
1173                       "AE&S", IDC_CIPHERAES, NULL);
1174             checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1175                      IDC_BUGGYMAC);
1176             endbox(&cp);
1177         }
1178     }
1179
1180     if (panel == tunnelspanelstart) {
1181         /* The Tunnels panel. Accelerators used: [acgo] ex */
1182         struct ctlpos cp;
1183         ctlposinit(&cp, hwnd, 80, 3, 13);
1184         if (dlgtype == 0) {
1185             bartitle(&cp, "Options controlling SSH tunnelling",
1186                      IDC_TITLE_TUNNELS);
1187             beginbox(&cp, "X11 forwarding options", IDC_BOX_TUNNELS);
1188             checkbox(&cp, "&Enable X11 forwarding", IDC_X11_FORWARD);
1189             multiedit(&cp, "&X display location", IDC_X11_DISPSTATIC,
1190                       IDC_X11_DISPLAY, 50, NULL);
1191             endbox(&cp);
1192         }
1193     }
1194 }
1195
1196 /*
1197  * This function is the configuration box.
1198  */
1199 static int GenericMainDlgProc(HWND hwnd, UINT msg,
1200                               WPARAM wParam, LPARAM lParam, int dlgtype)
1201 {
1202     HWND hw, treeview;
1203     struct treeview_faff tvfaff;
1204     HTREEITEM hsession;
1205     OPENFILENAME of;
1206     char filename[sizeof(cfg.keyfile)];
1207     CHOOSEFONT cf;
1208     LOGFONT lf;
1209     char fontstatic[256];
1210     char portname[32];
1211     struct servent *service;
1212     int i;
1213
1214     switch (msg) {
1215       case WM_INITDIALOG:
1216         readytogo = 0;
1217         SetWindowLong(hwnd, GWL_USERDATA, 0);
1218         SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
1219                     (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(IDI_CFGICON)));
1220         /*
1221          * Centre the window.
1222          */
1223         {                              /* centre the window */
1224             RECT rs, rd;
1225
1226             hw = GetDesktopWindow();
1227             if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))
1228                 MoveWindow(hwnd,
1229                            (rs.right + rs.left + rd.left - rd.right) / 2,
1230                            (rs.bottom + rs.top + rd.top - rd.bottom) / 2,
1231                            rd.right - rd.left, rd.bottom - rd.top, TRUE);
1232         }
1233
1234         /*
1235          * Create the tree view.
1236          */
1237         {
1238             RECT r;
1239             WPARAM font;
1240             HWND tvstatic;
1241
1242             r.left = 3;
1243             r.right = r.left + 75;
1244             r.top = 3;
1245             r.bottom = r.top + 10;
1246             MapDialogRect(hwnd, &r);
1247             tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1248                                       WS_CHILD | WS_VISIBLE,
1249                                       r.left, r.top,
1250                                       r.right - r.left, r.bottom - r.top,
1251                                       hwnd, (HMENU) IDCX_TVSTATIC, hinst,
1252                                       NULL);
1253             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1254             SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1255
1256             r.left = 3;
1257             r.right = r.left + 75;
1258             r.top = 13;
1259             r.bottom = r.top + 206;
1260             MapDialogRect(hwnd, &r);
1261             treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1262                                       WS_CHILD | WS_VISIBLE |
1263                                       WS_TABSTOP | TVS_HASLINES |
1264                                       TVS_DISABLEDRAGDROP | TVS_HASBUTTONS
1265                                       | TVS_LINESATROOT |
1266                                       TVS_SHOWSELALWAYS, r.left, r.top,
1267                                       r.right - r.left, r.bottom - r.top,
1268                                       hwnd, (HMENU) IDCX_TREEVIEW, hinst,
1269                                       NULL);
1270             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1271             SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1272             tvfaff.treeview = treeview;
1273             memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1274         }
1275
1276         /*
1277          * Set up the tree view contents.
1278          */
1279         hsession = treeview_insert(&tvfaff, 0, "Session");
1280         treeview_insert(&tvfaff, 1, "Logging");
1281         treeview_insert(&tvfaff, 0, "Terminal");
1282         treeview_insert(&tvfaff, 1, "Keyboard");
1283         treeview_insert(&tvfaff, 1, "Bell");
1284         treeview_insert(&tvfaff, 0, "Window");
1285         treeview_insert(&tvfaff, 1, "Appearance");
1286         treeview_insert(&tvfaff, 1, "Translation");
1287         treeview_insert(&tvfaff, 1, "Selection");
1288         treeview_insert(&tvfaff, 1, "Colours");
1289         treeview_insert(&tvfaff, 0, "Connection");
1290         if (dlgtype == 0) {
1291             treeview_insert(&tvfaff, 1, "Telnet");
1292             treeview_insert(&tvfaff, 1, "Rlogin");
1293             if (backends[3].backend != NULL) {
1294                 treeview_insert(&tvfaff, 1, "SSH");
1295                 treeview_insert(&tvfaff, 2, "Tunnels");
1296             }
1297         }
1298
1299         /*
1300          * Put the treeview selection on to the Session panel. This
1301          * should also cause creation of the relevant controls.
1302          */
1303         TreeView_SelectItem(treeview, hsession);
1304
1305         /*
1306          * Set focus into the first available control.
1307          */
1308         {
1309             HWND ctl;
1310             ctl = GetDlgItem(hwnd, IDC_HOST);
1311             if (!ctl)
1312                 ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1313             SetFocus(ctl);
1314         }
1315
1316         SetWindowLong(hwnd, GWL_USERDATA, 1);
1317         return 0;
1318       case WM_LBUTTONUP:
1319         /*
1320          * Button release should trigger WM_OK if there was a
1321          * previous double click on the session list.
1322          */
1323         ReleaseCapture();
1324         if (readytogo)
1325             SendMessage(hwnd, WM_COMMAND, IDOK, 0);
1326         break;
1327       case WM_NOTIFY:
1328         if (LOWORD(wParam) == IDCX_TREEVIEW &&
1329             ((LPNMHDR) lParam)->code == TVN_SELCHANGED) {
1330             HTREEITEM i =
1331                 TreeView_GetSelection(((LPNMHDR) lParam)->hwndFrom);
1332             TVITEM item;
1333             int j;
1334             char buffer[64];
1335             item.hItem = i;
1336             item.pszText = buffer;
1337             item.cchTextMax = sizeof(buffer);
1338             item.mask = TVIF_TEXT;
1339             TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &item);
1340             for (j = controlstartvalue; j < controlendvalue; j++) {
1341                 HWND item = GetDlgItem(hwnd, j);
1342                 if (item)
1343                     DestroyWindow(item);
1344             }
1345             if (!strcmp(buffer, "Session"))
1346                 create_controls(hwnd, dlgtype, sessionpanelstart);
1347             if (!strcmp(buffer, "Logging"))
1348                 create_controls(hwnd, dlgtype, loggingpanelstart);
1349             if (!strcmp(buffer, "Keyboard"))
1350                 create_controls(hwnd, dlgtype, keyboardpanelstart);
1351             if (!strcmp(buffer, "Terminal"))
1352                 create_controls(hwnd, dlgtype, terminalpanelstart);
1353             if (!strcmp(buffer, "Bell"))
1354                 create_controls(hwnd, dlgtype, bellpanelstart);
1355             if (!strcmp(buffer, "Window"))
1356                 create_controls(hwnd, dlgtype, windowpanelstart);
1357             if (!strcmp(buffer, "Appearance"))
1358                 create_controls(hwnd, dlgtype, appearancepanelstart);
1359             if (!strcmp(buffer, "Tunnels"))
1360                 create_controls(hwnd, dlgtype, tunnelspanelstart);
1361             if (!strcmp(buffer, "Connection"))
1362                 create_controls(hwnd, dlgtype, connectionpanelstart);
1363             if (!strcmp(buffer, "Telnet"))
1364                 create_controls(hwnd, dlgtype, telnetpanelstart);
1365             if (!strcmp(buffer, "Rlogin"))
1366                 create_controls(hwnd, dlgtype, rloginpanelstart);
1367             if (!strcmp(buffer, "SSH"))
1368                 create_controls(hwnd, dlgtype, sshpanelstart);
1369             if (!strcmp(buffer, "Selection"))
1370                 create_controls(hwnd, dlgtype, selectionpanelstart);
1371             if (!strcmp(buffer, "Colours"))
1372                 create_controls(hwnd, dlgtype, colourspanelstart);
1373             if (!strcmp(buffer, "Translation"))
1374                 create_controls(hwnd, dlgtype, translationpanelstart);
1375
1376             init_dlg_ctrls(hwnd);
1377
1378             SetFocus(((LPNMHDR) lParam)->hwndFrom);     /* ensure focus stays */
1379             return 0;
1380         }
1381         break;
1382       case WM_COMMAND:
1383         /*
1384          * Only process WM_COMMAND once the dialog is fully formed.
1385          */
1386         if (GetWindowLong(hwnd, GWL_USERDATA) == 1)
1387             switch (LOWORD(wParam)) {
1388               case IDOK:
1389                 if (*cfg.host)
1390                     EndDialog(hwnd, 1);
1391                 else
1392                     MessageBeep(0);
1393                 return 0;
1394               case IDCANCEL:
1395                 EndDialog(hwnd, 0);
1396                 return 0;
1397               case IDC_PROTTELNET:
1398               case IDC_PROTRLOGIN:
1399               case IDC_PROTSSH:
1400               case IDC_PROTRAW:
1401                 if (HIWORD(wParam) == BN_CLICKED ||
1402                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1403                     int i = IsDlgButtonChecked(hwnd, IDC_PROTSSH);
1404                     int j = IsDlgButtonChecked(hwnd, IDC_PROTTELNET);
1405                     int k = IsDlgButtonChecked(hwnd, IDC_PROTRLOGIN);
1406                     cfg.protocol =
1407                         i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN :
1408                         PROT_RAW;
1409                     if ((cfg.protocol == PROT_SSH && cfg.port != 22)
1410                         || (cfg.protocol == PROT_TELNET && cfg.port != 23)
1411                         || (cfg.protocol == PROT_RLOGIN
1412                             && cfg.port != 513)) {
1413                         cfg.port = i ? 22 : j ? 23 : 513;
1414                         SetDlgItemInt(hwnd, IDC_PORT, cfg.port, FALSE);
1415                     }
1416                 }
1417                 break;
1418               case IDC_HOST:
1419                 if (HIWORD(wParam) == EN_CHANGE)
1420                     GetDlgItemText(hwnd, IDC_HOST, cfg.host,
1421                                    sizeof(cfg.host) - 1);
1422                 break;
1423               case IDC_PORT:
1424                 if (HIWORD(wParam) == EN_CHANGE) {
1425                     GetDlgItemText(hwnd, IDC_PORT, portname, 31);
1426                     if (isdigit(portname[0]))
1427                         MyGetDlgItemInt(hwnd, IDC_PORT, &cfg.port);
1428                     else {
1429                         service = getservbyname(portname, NULL);
1430                         if (service)
1431                             cfg.port = ntohs(service->s_port);
1432                         else
1433                             cfg.port = 0;
1434                     }
1435                 }
1436                 break;
1437               case IDC_SESSEDIT:
1438                 if (HIWORD(wParam) == EN_CHANGE) {
1439                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1440                                        (WPARAM) - 1, 0);
1441                     GetDlgItemText(hwnd, IDC_SESSEDIT,
1442                                    savedsession, sizeof(savedsession) - 1);
1443                     savedsession[sizeof(savedsession) - 1] = '\0';
1444                 }
1445                 break;
1446               case IDC_SESSSAVE:
1447                 if (HIWORD(wParam) == BN_CLICKED ||
1448                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1449                     /*
1450                      * Save a session
1451                      */
1452                     char str[2048];
1453                     GetDlgItemText(hwnd, IDC_SESSEDIT, str,
1454                                    sizeof(str) - 1);
1455                     if (!*str) {
1456                         int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1457                                                    LB_GETCURSEL, 0, 0);
1458                         if (n == LB_ERR) {
1459                             MessageBeep(0);
1460                             break;
1461                         }
1462                         strcpy(str, sessions[n]);
1463                     }
1464                     save_settings(str, !!strcmp(str, "Default Settings"),
1465                                   &cfg);
1466                     get_sesslist(FALSE);
1467                     get_sesslist(TRUE);
1468                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1469                                        0, 0);
1470                     for (i = 0; i < nsessions; i++)
1471                         SendDlgItemMessage(hwnd, IDC_SESSLIST,
1472                                            LB_ADDSTRING, 0,
1473                                            (LPARAM) (sessions[i]));
1474                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1475                                        (WPARAM) - 1, 0);
1476                 }
1477                 break;
1478               case IDC_SESSLIST:
1479               case IDC_SESSLOAD:
1480                 if (LOWORD(wParam) == IDC_SESSLOAD &&
1481                     HIWORD(wParam) != BN_CLICKED &&
1482                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
1483                 if (LOWORD(wParam) == IDC_SESSLIST &&
1484                     HIWORD(wParam) != LBN_DBLCLK) break;
1485                 {
1486                     int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1487                                                LB_GETCURSEL, 0, 0);
1488                     int isdef;
1489                     if (n == LB_ERR) {
1490                         MessageBeep(0);
1491                         break;
1492                     }
1493                     isdef = !strcmp(sessions[n], "Default Settings");
1494                     load_settings(sessions[n], !isdef, &cfg);
1495                     init_dlg_ctrls(hwnd);
1496                     if (!isdef)
1497                         SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1498                     else
1499                         SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1500                 }
1501                 if (LOWORD(wParam) == IDC_SESSLIST) {
1502                     /*
1503                      * A double-click on a saved session should
1504                      * actually start the session, not just load it.
1505                      * Unless it's Default Settings or some other
1506                      * host-less set of saved settings.
1507                      */
1508                     if (*cfg.host) {
1509                         readytogo = TRUE;
1510                         SetCapture(hwnd);
1511                     }
1512                 }
1513                 break;
1514               case IDC_SESSDEL:
1515                 if (HIWORD(wParam) == BN_CLICKED ||
1516                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1517                     int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1518                                                LB_GETCURSEL, 0, 0);
1519                     if (n == LB_ERR || n == 0) {
1520                         MessageBeep(0);
1521                         break;
1522                     }
1523                     del_settings(sessions[n]);
1524                     get_sesslist(FALSE);
1525                     get_sesslist(TRUE);
1526                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1527                                        0, 0);
1528                     for (i = 0; i < nsessions; i++)
1529                         SendDlgItemMessage(hwnd, IDC_SESSLIST,
1530                                            LB_ADDSTRING, 0,
1531                                            (LPARAM) (sessions[i]));
1532                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1533                                        (WPARAM) - 1, 0);
1534                 }
1535               case IDC_PINGEDIT:
1536                 if (HIWORD(wParam) == EN_CHANGE)
1537                     MyGetDlgItemInt(hwnd, IDC_PINGEDIT,
1538                                     &cfg.ping_interval);
1539                 break;
1540               case IDC_DEL008:
1541               case IDC_DEL127:
1542                 if (HIWORD(wParam) == BN_CLICKED ||
1543                     HIWORD(wParam) == BN_DOUBLECLICKED)
1544                         cfg.bksp_is_delete =
1545                         IsDlgButtonChecked(hwnd, IDC_DEL127);
1546                 break;
1547               case IDC_HOMETILDE:
1548               case IDC_HOMERXVT:
1549                 if (HIWORD(wParam) == BN_CLICKED ||
1550                     HIWORD(wParam) == BN_DOUBLECLICKED)
1551                         cfg.rxvt_homeend =
1552                         IsDlgButtonChecked(hwnd, IDC_HOMERXVT);
1553                 break;
1554               case IDC_FUNCTILDE:
1555               case IDC_FUNCLINUX:
1556               case IDC_FUNCXTERM:
1557               case IDC_FUNCVT400:
1558               case IDC_FUNCVT100P:
1559               case IDC_FUNCSCO:
1560                 if (HIWORD(wParam) == BN_CLICKED ||
1561                     HIWORD(wParam) == BN_DOUBLECLICKED)
1562                         switch (LOWORD(wParam)) {
1563                       case IDC_FUNCTILDE:
1564                         cfg.funky_type = 0;
1565                         break;
1566                       case IDC_FUNCLINUX:
1567                         cfg.funky_type = 1;
1568                         break;
1569                       case IDC_FUNCXTERM:
1570                         cfg.funky_type = 2;
1571                         break;
1572                       case IDC_FUNCVT400:
1573                         cfg.funky_type = 3;
1574                         break;
1575                       case IDC_FUNCVT100P:
1576                         cfg.funky_type = 4;
1577                         break;
1578                       case IDC_FUNCSCO:
1579                         cfg.funky_type = 5;
1580                         break;
1581                     }
1582                 break;
1583               case IDC_KPNORMAL:
1584               case IDC_KPAPPLIC:
1585                 if (HIWORD(wParam) == BN_CLICKED ||
1586                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1587                     cfg.app_keypad =
1588                         IsDlgButtonChecked(hwnd, IDC_KPAPPLIC);
1589                     cfg.nethack_keypad = FALSE;
1590                 }
1591                 break;
1592               case IDC_KPNH:
1593                 if (HIWORD(wParam) == BN_CLICKED ||
1594                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1595                     cfg.app_keypad = FALSE;
1596                     cfg.nethack_keypad = TRUE;
1597                 }
1598                 break;
1599               case IDC_CURNORMAL:
1600               case IDC_CURAPPLIC:
1601                 if (HIWORD(wParam) == BN_CLICKED ||
1602                     HIWORD(wParam) == BN_DOUBLECLICKED)
1603                         cfg.app_cursor =
1604                         IsDlgButtonChecked(hwnd, IDC_CURAPPLIC);
1605                 break;
1606               case IDC_NOAPPLICC:
1607                 if (HIWORD(wParam) == BN_CLICKED ||
1608                     HIWORD(wParam) == BN_DOUBLECLICKED)
1609                         cfg.no_applic_c =
1610                         IsDlgButtonChecked(hwnd, IDC_NOAPPLICC);
1611                 break;
1612               case IDC_NOAPPLICK:
1613                 if (HIWORD(wParam) == BN_CLICKED ||
1614                     HIWORD(wParam) == BN_DOUBLECLICKED)
1615                         cfg.no_applic_k =
1616                         IsDlgButtonChecked(hwnd, IDC_NOAPPLICK);
1617                 break;
1618               case IDC_ALTF4:
1619                 if (HIWORD(wParam) == BN_CLICKED ||
1620                     HIWORD(wParam) == BN_DOUBLECLICKED)
1621                         cfg.alt_f4 = IsDlgButtonChecked(hwnd, IDC_ALTF4);
1622                 break;
1623               case IDC_ALTSPACE:
1624                 if (HIWORD(wParam) == BN_CLICKED ||
1625                     HIWORD(wParam) == BN_DOUBLECLICKED)
1626                         cfg.alt_space =
1627                         IsDlgButtonChecked(hwnd, IDC_ALTSPACE);
1628                 break;
1629               case IDC_ALTONLY:
1630                 if (HIWORD(wParam) == BN_CLICKED ||
1631                     HIWORD(wParam) == BN_DOUBLECLICKED)
1632                         cfg.alt_only =
1633                         IsDlgButtonChecked(hwnd, IDC_ALTONLY);
1634                 break;
1635               case IDC_ECHOBACKEND:
1636               case IDC_ECHOYES:
1637               case IDC_ECHONO:
1638                 if (HIWORD(wParam) == BN_CLICKED ||
1639                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1640                     if (LOWORD(wParam) == IDC_ECHOBACKEND)
1641                         cfg.localecho = LD_BACKEND;
1642                     if (LOWORD(wParam) == IDC_ECHOYES)
1643                         cfg.localecho = LD_YES;
1644                     if (LOWORD(wParam) == IDC_ECHONO)
1645                         cfg.localecho = LD_NO;
1646                 }
1647                 break;
1648               case IDC_EDITBACKEND:
1649               case IDC_EDITYES:
1650               case IDC_EDITNO:
1651                 if (HIWORD(wParam) == BN_CLICKED ||
1652                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1653                     if (LOWORD(wParam) == IDC_EDITBACKEND)
1654                         cfg.localedit = LD_BACKEND;
1655                     if (LOWORD(wParam) == IDC_EDITYES)
1656                         cfg.localedit = LD_YES;
1657                     if (LOWORD(wParam) == IDC_EDITNO)
1658                         cfg.localedit = LD_NO;
1659                 }
1660                 break;
1661               case IDC_ANSWEREDIT:
1662                 if (HIWORD(wParam) == EN_CHANGE)
1663                     GetDlgItemText(hwnd, IDC_ANSWEREDIT, cfg.answerback,
1664                                    sizeof(cfg.answerback) - 1);
1665                 break;
1666               case IDC_ALWAYSONTOP:
1667                 if (HIWORD(wParam) == BN_CLICKED ||
1668                     HIWORD(wParam) == BN_DOUBLECLICKED)
1669                         cfg.alwaysontop =
1670                         IsDlgButtonChecked(hwnd, IDC_ALWAYSONTOP);
1671                 break;
1672               case IDC_SCROLLKEY:
1673                 if (HIWORD(wParam) == BN_CLICKED ||
1674                     HIWORD(wParam) == BN_DOUBLECLICKED)
1675                         cfg.scroll_on_key =
1676                         IsDlgButtonChecked(hwnd, IDC_SCROLLKEY);
1677                 break;
1678               case IDC_SCROLLDISP:
1679                 if (HIWORD(wParam) == BN_CLICKED ||
1680                     HIWORD(wParam) == BN_DOUBLECLICKED)
1681                         cfg.scroll_on_disp =
1682                         IsDlgButtonChecked(hwnd, IDC_SCROLLDISP);
1683                 break;
1684               case IDC_COMPOSEKEY:
1685                 if (HIWORD(wParam) == BN_CLICKED ||
1686                     HIWORD(wParam) == BN_DOUBLECLICKED)
1687                         cfg.compose_key =
1688                         IsDlgButtonChecked(hwnd, IDC_COMPOSEKEY);
1689                 break;
1690               case IDC_CTRLALTKEYS:
1691                 if (HIWORD(wParam) == BN_CLICKED ||
1692                     HIWORD(wParam) == BN_DOUBLECLICKED)
1693                         cfg.ctrlaltkeys =
1694                         IsDlgButtonChecked(hwnd, IDC_CTRLALTKEYS);
1695                 break;
1696               case IDC_TELNETKEY:
1697                 if (HIWORD(wParam) == BN_CLICKED ||
1698                     HIWORD(wParam) == BN_DOUBLECLICKED)
1699                         cfg.telnet_keyboard =
1700                         IsDlgButtonChecked(hwnd, IDC_TELNETKEY);
1701                 break;
1702               case IDC_WRAPMODE:
1703                 if (HIWORD(wParam) == BN_CLICKED ||
1704                     HIWORD(wParam) == BN_DOUBLECLICKED)
1705                         cfg.wrap_mode =
1706                         IsDlgButtonChecked(hwnd, IDC_WRAPMODE);
1707                 break;
1708               case IDC_DECOM:
1709                 if (HIWORD(wParam) == BN_CLICKED ||
1710                     HIWORD(wParam) == BN_DOUBLECLICKED)
1711                         cfg.dec_om = IsDlgButtonChecked(hwnd, IDC_DECOM);
1712                 break;
1713               case IDC_LFHASCR:
1714                 if (HIWORD(wParam) == BN_CLICKED ||
1715                     HIWORD(wParam) == BN_DOUBLECLICKED)
1716                         cfg.lfhascr =
1717                         IsDlgButtonChecked(hwnd, IDC_LFHASCR);
1718                 break;
1719               case IDC_ROWSEDIT:
1720                 if (HIWORD(wParam) == EN_CHANGE)
1721                     MyGetDlgItemInt(hwnd, IDC_ROWSEDIT, &cfg.height);
1722                 break;
1723               case IDC_COLSEDIT:
1724                 if (HIWORD(wParam) == EN_CHANGE)
1725                     MyGetDlgItemInt(hwnd, IDC_COLSEDIT, &cfg.width);
1726                 break;
1727               case IDC_SAVEEDIT:
1728                 if (HIWORD(wParam) == EN_CHANGE)
1729                     MyGetDlgItemInt(hwnd, IDC_SAVEEDIT, &cfg.savelines);
1730                 break;
1731               case IDC_CHOOSEFONT:
1732                 {
1733                     HDC hdc = GetDC(0);
1734                     lf.lfHeight = -MulDiv(cfg.fontheight,
1735                                           GetDeviceCaps(hdc, LOGPIXELSY),
1736                                           72);
1737                     ReleaseDC(0, hdc);
1738                 }
1739                 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1740                 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1741                 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1742                 lf.lfCharSet = cfg.fontcharset;
1743                 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1744                 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1745                 lf.lfQuality = DEFAULT_QUALITY;
1746                 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1747                 strncpy(lf.lfFaceName, cfg.font,
1748                         sizeof(lf.lfFaceName) - 1);
1749                 lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
1750
1751                 cf.lStructSize = sizeof(cf);
1752                 cf.hwndOwner = hwnd;
1753                 cf.lpLogFont = &lf;
1754                 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1755                     CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1756
1757                 if (ChooseFont(&cf)) {
1758                     strncpy(cfg.font, lf.lfFaceName, sizeof(cfg.font) - 1);
1759                     cfg.font[sizeof(cfg.font) - 1] = '\0';
1760                     cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1761                     cfg.fontcharset = lf.lfCharSet;
1762                     cfg.fontheight = cf.iPointSize / 10;
1763                     fmtfont(fontstatic);
1764                     SetDlgItemText(hwnd, IDC_FONTSTATIC, fontstatic);
1765                 }
1766                 break;
1767               case IDC_BELL_DISABLED:
1768               case IDC_BELL_DEFAULT:
1769               case IDC_BELL_WAVEFILE:
1770               case IDC_BELL_VISUAL:
1771                 if (HIWORD(wParam) == BN_CLICKED ||
1772                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1773                     if (LOWORD(wParam) == IDC_BELL_DISABLED)
1774                         cfg.beep = BELL_DISABLED;
1775                     if (LOWORD(wParam) == IDC_BELL_DEFAULT)
1776                         cfg.beep = BELL_DEFAULT;
1777                     if (LOWORD(wParam) == IDC_BELL_WAVEFILE)
1778                         cfg.beep = BELL_WAVEFILE;
1779                     if (LOWORD(wParam) == IDC_BELL_VISUAL)
1780                         cfg.beep = BELL_VISUAL;
1781                 }
1782                 break;
1783               case IDC_BELL_WAVEBROWSE:
1784                 memset(&of, 0, sizeof(of));
1785 #ifdef OPENFILENAME_SIZE_VERSION_400
1786                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1787 #else
1788                 of.lStructSize = sizeof(of);
1789 #endif
1790                 of.hwndOwner = hwnd;
1791                 of.lpstrFilter = "Wave Files\0*.WAV\0AllFiles\0*\0\0\0";
1792                 of.lpstrCustomFilter = NULL;
1793                 of.nFilterIndex = 1;
1794                 of.lpstrFile = filename;
1795                 strcpy(filename, cfg.bell_wavefile);
1796                 of.nMaxFile = sizeof(filename);
1797                 of.lpstrFileTitle = NULL;
1798                 of.lpstrInitialDir = NULL;
1799                 of.lpstrTitle = "Select Bell Sound File";
1800                 of.Flags = 0;
1801                 if (GetOpenFileName(&of)) {
1802                     strcpy(cfg.bell_wavefile, filename);
1803                     SetDlgItemText(hwnd, IDC_BELL_WAVEEDIT,
1804                                    cfg.bell_wavefile);
1805                 }
1806                 break;
1807               case IDC_BELL_WAVEEDIT:
1808                 if (HIWORD(wParam) == EN_CHANGE)
1809                     GetDlgItemText(hwnd, IDC_BELL_WAVEEDIT,
1810                                    cfg.bell_wavefile,
1811                                    sizeof(cfg.bell_wavefile) - 1);
1812                 break;
1813               case IDC_BELLOVL:
1814                 if (HIWORD(wParam) == BN_CLICKED ||
1815                     HIWORD(wParam) == BN_DOUBLECLICKED)
1816                         cfg.bellovl =
1817                         IsDlgButtonChecked(hwnd, IDC_BELLOVL);
1818                 break;
1819               case IDC_BELLOVLN:
1820                 if (HIWORD(wParam) == EN_CHANGE)
1821                     MyGetDlgItemInt(hwnd, IDC_BELLOVLN, &cfg.bellovl_n);
1822                 break;
1823               case IDC_BELLOVLT:
1824                 if (HIWORD(wParam) == EN_CHANGE)
1825                     MyGetDlgItemFlt(hwnd, IDC_BELLOVLT, &cfg.bellovl_t,
1826                                     1000);
1827                 break;
1828               case IDC_BELLOVLS:
1829                 if (HIWORD(wParam) == EN_CHANGE)
1830                     MyGetDlgItemFlt(hwnd, IDC_BELLOVLS, &cfg.bellovl_s,
1831                                     1000);
1832                 break;
1833               case IDC_BLINKTEXT:
1834                 if (HIWORD(wParam) == BN_CLICKED ||
1835                     HIWORD(wParam) == BN_DOUBLECLICKED)
1836                         cfg.blinktext =
1837                         IsDlgButtonChecked(hwnd, IDC_BLINKTEXT);
1838                 break;
1839               case IDC_BCE:
1840                 if (HIWORD(wParam) == BN_CLICKED ||
1841                     HIWORD(wParam) == BN_DOUBLECLICKED)
1842                         cfg.bce = IsDlgButtonChecked(hwnd, IDC_BCE);
1843                 break;
1844               case IDC_WINNAME:
1845                 if (HIWORD(wParam) == BN_CLICKED ||
1846                     HIWORD(wParam) == BN_DOUBLECLICKED)
1847                         cfg.win_name_always =
1848                         IsDlgButtonChecked(hwnd, IDC_WINNAME);
1849                 break;
1850               case IDC_HIDEMOUSE:
1851                 if (HIWORD(wParam) == BN_CLICKED ||
1852                     HIWORD(wParam) == BN_DOUBLECLICKED)
1853                         cfg.hide_mouseptr =
1854                         IsDlgButtonChecked(hwnd, IDC_HIDEMOUSE);
1855                 break;
1856               case IDC_SUNKENEDGE:
1857                 if (HIWORD(wParam) == BN_CLICKED ||
1858                     HIWORD(wParam) == BN_DOUBLECLICKED)
1859                         cfg.sunken_edge =
1860                         IsDlgButtonChecked(hwnd, IDC_SUNKENEDGE);
1861                 break;
1862               case IDC_CURBLOCK:
1863                 if (HIWORD(wParam) == BN_CLICKED ||
1864                     HIWORD(wParam) == BN_DOUBLECLICKED)
1865                         cfg.cursor_type = 0;
1866                 break;
1867               case IDC_CURUNDER:
1868                 if (HIWORD(wParam) == BN_CLICKED ||
1869                     HIWORD(wParam) == BN_DOUBLECLICKED)
1870                         cfg.cursor_type = 1;
1871                 break;
1872               case IDC_CURVERT:
1873                 if (HIWORD(wParam) == BN_CLICKED ||
1874                     HIWORD(wParam) == BN_DOUBLECLICKED)
1875                         cfg.cursor_type = 2;
1876                 break;
1877               case IDC_BLINKCUR:
1878                 if (HIWORD(wParam) == BN_CLICKED ||
1879                     HIWORD(wParam) == BN_DOUBLECLICKED)
1880                         cfg.blink_cur =
1881                         IsDlgButtonChecked(hwnd, IDC_BLINKCUR);
1882                 break;
1883               case IDC_SCROLLBAR:
1884                 if (HIWORD(wParam) == BN_CLICKED ||
1885                     HIWORD(wParam) == BN_DOUBLECLICKED)
1886                         cfg.scrollbar =
1887                         IsDlgButtonChecked(hwnd, IDC_SCROLLBAR);
1888                 break;
1889               case IDC_LOCKSIZE:
1890                 if (HIWORD(wParam) == BN_CLICKED ||
1891                     HIWORD(wParam) == BN_DOUBLECLICKED)
1892                         cfg.locksize =
1893                         IsDlgButtonChecked(hwnd, IDC_LOCKSIZE);
1894                 break;
1895               case IDC_WINEDIT:
1896                 if (HIWORD(wParam) == EN_CHANGE)
1897                     GetDlgItemText(hwnd, IDC_WINEDIT, cfg.wintitle,
1898                                    sizeof(cfg.wintitle) - 1);
1899                 break;
1900               case IDC_COEALWAYS:
1901               case IDC_COENEVER:
1902               case IDC_COENORMAL:
1903                 if (HIWORD(wParam) == BN_CLICKED ||
1904                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1905                     cfg.close_on_exit =
1906                         IsDlgButtonChecked(hwnd,
1907                                            IDC_COEALWAYS) ? COE_ALWAYS :
1908                         IsDlgButtonChecked(hwnd,
1909                                            IDC_COENEVER) ? COE_NEVER :
1910                         COE_NORMAL;
1911                 }
1912                 break;
1913               case IDC_CLOSEWARN:
1914                 if (HIWORD(wParam) == BN_CLICKED ||
1915                     HIWORD(wParam) == BN_DOUBLECLICKED)
1916                         cfg.warn_on_close =
1917                         IsDlgButtonChecked(hwnd, IDC_CLOSEWARN);
1918                 break;
1919               case IDC_TTEDIT:
1920                 if (HIWORD(wParam) == EN_CHANGE)
1921                     GetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype,
1922                                    sizeof(cfg.termtype) - 1);
1923                 break;
1924               case IDC_LGFEDIT:
1925                 if (HIWORD(wParam) == EN_CHANGE)
1926                     GetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename,
1927                                    sizeof(cfg.logfilename) - 1);
1928                 break;
1929               case IDC_LGFBUTTON:
1930                 memset(&of, 0, sizeof(of));
1931 #ifdef OPENFILENAME_SIZE_VERSION_400
1932                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1933 #else
1934                 of.lStructSize = sizeof(of);
1935 #endif
1936                 of.hwndOwner = hwnd;
1937                 of.lpstrFilter = "All Files\0*\0\0\0";
1938                 of.lpstrCustomFilter = NULL;
1939                 of.nFilterIndex = 1;
1940                 of.lpstrFile = filename;
1941                 strcpy(filename, cfg.logfilename);
1942                 of.nMaxFile = sizeof(filename);
1943                 of.lpstrFileTitle = NULL;
1944                 of.lpstrInitialDir = NULL;
1945                 of.lpstrTitle = "Select session log file";
1946                 of.Flags = 0;
1947                 if (GetSaveFileName(&of)) {
1948                     strcpy(cfg.logfilename, filename);
1949                     SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
1950                 }
1951                 break;
1952               case IDC_LSTATOFF:
1953               case IDC_LSTATASCII:
1954               case IDC_LSTATRAW:
1955                 if (HIWORD(wParam) == BN_CLICKED ||
1956                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1957                     if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF))
1958                         cfg.logtype = 0;
1959                     if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII))
1960                         cfg.logtype = 1;
1961                     if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW))
1962                         cfg.logtype = 2;
1963                 }
1964                 break;
1965               case IDC_LSTATXASK:
1966               case IDC_LSTATXAPN:
1967               case IDC_LSTATXOVR:
1968                 if (HIWORD(wParam) == BN_CLICKED ||
1969                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1970                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXASK))
1971                         cfg.logxfovr = LGXF_ASK;
1972                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXAPN))
1973                         cfg.logxfovr = LGXF_APN;
1974                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXOVR))
1975                         cfg.logxfovr = LGXF_OVR;
1976                 }
1977                 break;
1978               case IDC_TSEDIT:
1979               case IDC_R_TSEDIT:
1980                 if (HIWORD(wParam) == EN_CHANGE)
1981                     GetDlgItemText(hwnd, LOWORD(wParam), cfg.termspeed,
1982                                    sizeof(cfg.termspeed) - 1);
1983                 break;
1984               case IDC_LOGEDIT:
1985                 if (HIWORD(wParam) == EN_CHANGE)
1986                     GetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username,
1987                                    sizeof(cfg.username) - 1);
1988                 break;
1989               case IDC_RLLUSEREDIT:
1990                 if (HIWORD(wParam) == EN_CHANGE)
1991                     GetDlgItemText(hwnd, IDC_RLLUSEREDIT,
1992                                    cfg.localusername,
1993                                    sizeof(cfg.localusername) - 1);
1994                 break;
1995               case IDC_EMBSD:
1996               case IDC_EMRFC:
1997                 cfg.rfc_environ = IsDlgButtonChecked(hwnd, IDC_EMRFC);
1998                 break;
1999               case IDC_TPASSIVE:
2000               case IDC_TACTIVE:
2001                 cfg.passive_telnet =
2002                     IsDlgButtonChecked(hwnd, IDC_TPASSIVE);
2003                 break;
2004               case IDC_ENVADD:
2005                 if (HIWORD(wParam) == BN_CLICKED ||
2006                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2007                     char str[sizeof(cfg.environmt)];
2008                     char *p;
2009                     GetDlgItemText(hwnd, IDC_VAREDIT, str,
2010                                    sizeof(str) - 1);
2011                     if (!*str) {
2012                         MessageBeep(0);
2013                         break;
2014                     }
2015                     p = str + strlen(str);
2016                     *p++ = '\t';
2017                     GetDlgItemText(hwnd, IDC_VALEDIT, p,
2018                                    sizeof(str) - 1 - (p - str));
2019                     if (!*p) {
2020                         MessageBeep(0);
2021                         break;
2022                     }
2023                     p = cfg.environmt;
2024                     while (*p) {
2025                         while (*p)
2026                             p++;
2027                         p++;
2028                     }
2029                     if ((p - cfg.environmt) + strlen(str) + 2 <
2030                         sizeof(cfg.environmt)) {
2031                         strcpy(p, str);
2032                         p[strlen(str) + 1] = '\0';
2033                         SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_ADDSTRING,
2034                                            0, (LPARAM) str);
2035                         SetDlgItemText(hwnd, IDC_VAREDIT, "");
2036                         SetDlgItemText(hwnd, IDC_VALEDIT, "");
2037                     } else {
2038                         MessageBox(hwnd, "Environment too big",
2039                                    "PuTTY Error", MB_OK | MB_ICONERROR);
2040                     }
2041                 }
2042                 break;
2043               case IDC_ENVREMOVE:
2044                 if (HIWORD(wParam) != BN_CLICKED &&
2045                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
2046                 i =
2047                     SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_GETCURSEL, 0,
2048                                        0);
2049                 if (i == LB_ERR)
2050                     MessageBeep(0);
2051                 else {
2052                     char *p, *q;
2053
2054                     SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_DELETESTRING,
2055                                        i, 0);
2056                     p = cfg.environmt;
2057                     while (i > 0) {
2058                         if (!*p)
2059                             goto disaster;
2060                         while (*p)
2061                             p++;
2062                         p++;
2063                         i--;
2064                     }
2065                     q = p;
2066                     if (!*p)
2067                         goto disaster;
2068                     while (*p)
2069                         p++;
2070                     p++;
2071                     while (*p) {
2072                         while (*p)
2073                             *q++ = *p++;
2074                         *q++ = *p++;
2075                     }
2076                     *q = '\0';
2077                   disaster:;
2078                 }
2079                 break;
2080               case IDC_NOPTY:
2081                 if (HIWORD(wParam) == BN_CLICKED ||
2082                     HIWORD(wParam) == BN_DOUBLECLICKED)
2083                         cfg.nopty = IsDlgButtonChecked(hwnd, IDC_NOPTY);
2084                 break;
2085               case IDC_COMPRESS:
2086                 if (HIWORD(wParam) == BN_CLICKED ||
2087                     HIWORD(wParam) == BN_DOUBLECLICKED)
2088                         cfg.compression =
2089                         IsDlgButtonChecked(hwnd, IDC_COMPRESS);
2090                 break;
2091               case IDC_BUGGYMAC:
2092                 if (HIWORD(wParam) == BN_CLICKED ||
2093                     HIWORD(wParam) == BN_DOUBLECLICKED)
2094                         cfg.buggymac =
2095                         IsDlgButtonChecked(hwnd, IDC_BUGGYMAC);
2096                 break;
2097               case IDC_AGENTFWD:
2098                 if (HIWORD(wParam) == BN_CLICKED ||
2099                     HIWORD(wParam) == BN_DOUBLECLICKED)
2100                         cfg.agentfwd =
2101                         IsDlgButtonChecked(hwnd, IDC_AGENTFWD);
2102                 break;
2103               case IDC_CIPHER3DES:
2104               case IDC_CIPHERBLOWF:
2105               case IDC_CIPHERDES:
2106               case IDC_CIPHERAES:
2107                 if (HIWORD(wParam) == BN_CLICKED ||
2108                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2109                     if (IsDlgButtonChecked(hwnd, IDC_CIPHER3DES))
2110                         cfg.cipher = CIPHER_3DES;
2111                     else if (IsDlgButtonChecked(hwnd, IDC_CIPHERBLOWF))
2112                         cfg.cipher = CIPHER_BLOWFISH;
2113                     else if (IsDlgButtonChecked(hwnd, IDC_CIPHERDES))
2114                         cfg.cipher = CIPHER_DES;
2115                     else if (IsDlgButtonChecked(hwnd, IDC_CIPHERAES))
2116                         cfg.cipher = CIPHER_AES;
2117                 }
2118                 break;
2119               case IDC_SSHPROT1:
2120               case IDC_SSHPROT2:
2121                 if (HIWORD(wParam) == BN_CLICKED ||
2122                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2123                     if (IsDlgButtonChecked(hwnd, IDC_SSHPROT1))
2124                         cfg.sshprot = 1;
2125                     else if (IsDlgButtonChecked(hwnd, IDC_SSHPROT2))
2126                         cfg.sshprot = 2;
2127                 }
2128                 break;
2129               case IDC_AUTHTIS:
2130                 if (HIWORD(wParam) == BN_CLICKED ||
2131                     HIWORD(wParam) == BN_DOUBLECLICKED)
2132                         cfg.try_tis_auth =
2133                         IsDlgButtonChecked(hwnd, IDC_AUTHTIS);
2134                 break;
2135               case IDC_PKEDIT:
2136                 if (HIWORD(wParam) == EN_CHANGE)
2137                     GetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile,
2138                                    sizeof(cfg.keyfile) - 1);
2139                 break;
2140               case IDC_CMDEDIT:
2141                 if (HIWORD(wParam) == EN_CHANGE)
2142                     GetDlgItemText(hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2143                                    sizeof(cfg.remote_cmd) - 1);
2144                 break;
2145               case IDC_PKBUTTON:
2146                 memset(&of, 0, sizeof(of));
2147 #ifdef OPENFILENAME_SIZE_VERSION_400
2148                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2149 #else
2150                 of.lStructSize = sizeof(of);
2151 #endif
2152                 of.hwndOwner = hwnd;
2153                 of.lpstrFilter = "All Files\0*\0\0\0";
2154                 of.lpstrCustomFilter = NULL;
2155                 of.nFilterIndex = 1;
2156                 of.lpstrFile = filename;
2157                 strcpy(filename, cfg.keyfile);
2158                 of.nMaxFile = sizeof(filename);
2159                 of.lpstrFileTitle = NULL;
2160                 of.lpstrInitialDir = NULL;
2161                 of.lpstrTitle = "Select Public Key File";
2162                 of.Flags = 0;
2163                 if (GetOpenFileName(&of)) {
2164                     strcpy(cfg.keyfile, filename);
2165                     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
2166                 }
2167                 break;
2168               case IDC_RAWCNP:
2169                 cfg.rawcnp = IsDlgButtonChecked(hwnd, IDC_RAWCNP);
2170               case IDC_MBWINDOWS:
2171               case IDC_MBXTERM:
2172                 cfg.mouse_is_xterm = IsDlgButtonChecked(hwnd, IDC_MBXTERM);
2173                 break;
2174               case IDC_CCSET:
2175                 {
2176                     BOOL ok;
2177                     int i;
2178                     int n = GetDlgItemInt(hwnd, IDC_CCEDIT, &ok, FALSE);
2179
2180                     if (!ok)
2181                         MessageBeep(0);
2182                     else {
2183                         for (i = 0; i < 128; i++)
2184                             if (SendDlgItemMessage
2185                                 (hwnd, IDC_CCLIST, LB_GETSEL, i, 0)) {
2186                                 char str[100];
2187                                 cfg.wordness[i] = n;
2188                                 SendDlgItemMessage(hwnd, IDC_CCLIST,
2189                                                    LB_DELETESTRING, i, 0);
2190                                 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2191                                         (i >= 0x21 && i != 0x7F) ? i : ' ',
2192                                         cfg.wordness[i]);
2193                                 SendDlgItemMessage(hwnd, IDC_CCLIST,
2194                                                    LB_INSERTSTRING, i,
2195                                                    (LPARAM) str);
2196                             }
2197                     }
2198                 }
2199                 break;
2200               case IDC_BOLDCOLOUR:
2201                 if (HIWORD(wParam) == BN_CLICKED ||
2202                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2203                     int n, i;
2204                     cfg.bold_colour =
2205                         IsDlgButtonChecked(hwnd, IDC_BOLDCOLOUR);
2206                     n =
2207                         SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2208                                            LB_GETCOUNT, 0, 0);
2209                     if (n != 12 + 10 * cfg.bold_colour) {
2210                         for (i = n; i-- > 0;)
2211                             SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2212                                                LB_DELETESTRING, i, 0);
2213                         for (i = 0; i < 22; i++)
2214                             if (cfg.bold_colour || permcolour[i])
2215                                 SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2216                                                    LB_ADDSTRING, 0,
2217                                                    (LPARAM) colours[i]);
2218                     }
2219                 }
2220                 break;
2221               case IDC_PALETTE:
2222                 if (HIWORD(wParam) == BN_CLICKED ||
2223                     HIWORD(wParam) == BN_DOUBLECLICKED)
2224                         cfg.try_palette =
2225                         IsDlgButtonChecked(hwnd, IDC_PALETTE);
2226                 break;
2227               case IDC_COLOURLIST:
2228                 if (HIWORD(wParam) == LBN_DBLCLK ||
2229                     HIWORD(wParam) == LBN_SELCHANGE) {
2230                     int i = SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2231                                                LB_GETCURSEL,
2232                                                0, 0);
2233                     if (!cfg.bold_colour)
2234                         i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
2235                     SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
2236                                   FALSE);
2237                     SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[i][1],
2238                                   FALSE);
2239                     SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[i][2],
2240                                   FALSE);
2241                 }
2242                 break;
2243               case IDC_CHANGE:
2244                 if (HIWORD(wParam) == BN_CLICKED ||
2245                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2246                     static CHOOSECOLOR cc;
2247                     static DWORD custom[16] = { 0 };    /* zero initialisers */
2248                     int i = SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2249                                                LB_GETCURSEL,
2250                                                0, 0);
2251                     if (!cfg.bold_colour)
2252                         i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
2253                     cc.lStructSize = sizeof(cc);
2254                     cc.hwndOwner = hwnd;
2255                     cc.hInstance = (HWND) hinst;
2256                     cc.lpCustColors = custom;
2257                     cc.rgbResult =
2258                         RGB(cfg.colours[i][0], cfg.colours[i][1],
2259                             cfg.colours[i][2]);
2260                     cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2261                     if (ChooseColor(&cc)) {
2262                         cfg.colours[i][0] =
2263                             (unsigned char) (cc.rgbResult & 0xFF);
2264                         cfg.colours[i][1] =
2265                             (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2266                         cfg.colours[i][2] =
2267                             (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2268                         SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
2269                                       FALSE);
2270                         SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[i][1],
2271                                       FALSE);
2272                         SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[i][2],
2273                                       FALSE);
2274                     }
2275                 }
2276                 break;
2277               case IDC_CODEPAGE:
2278                 if (HIWORD(wParam) == EN_CHANGE)
2279                     GetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage,
2280                                    sizeof(cfg.line_codepage) - 1);
2281                 if (HIWORD(wParam) == EN_KILLFOCUS) {
2282                     int cp = decode_codepage(cfg.line_codepage);
2283                     char buf[256];
2284                     if (cp < -1) {
2285                         if (cp == -2)
2286                             sprintf(buf,
2287                                     "Unable to identify character set '%s', "
2288                                     "translation disabled.",
2289                                     cfg.line_codepage);
2290                         if (cp == -3)
2291                             sprintf(buf,
2292                                     "Character set '%s' is a DBCS, "
2293                                     "translation is not available.",
2294                                     cfg.line_codepage);
2295                         MessageBox(hwnd, buf, "PuTTY Error",
2296                                    MB_ICONERROR | MB_OK);
2297                     }
2298                     strcpy(cfg.line_codepage, cp_name(cp));
2299                     SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
2300                 }
2301                 break;
2302               case IDC_VTXWINDOWS:
2303               case IDC_VTOEMANSI:
2304               case IDC_VTOEMONLY:
2305               case IDC_VTPOORMAN:
2306               case IDC_VTUNICODE:
2307                 cfg.vtmode =
2308                     (IsDlgButtonChecked(hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS
2309                      : IsDlgButtonChecked(hwnd,
2310                                           IDC_VTOEMANSI) ? VT_OEMANSI :
2311                      IsDlgButtonChecked(hwnd,
2312                                         IDC_VTOEMONLY) ? VT_OEMONLY :
2313                      IsDlgButtonChecked(hwnd,
2314                                         IDC_VTUNICODE) ? VT_UNICODE :
2315                      VT_POORMAN);
2316                 break;
2317               case IDC_X11_FORWARD:
2318                 if (HIWORD(wParam) == BN_CLICKED ||
2319                     HIWORD(wParam) == BN_DOUBLECLICKED)
2320                         cfg.x11_forward =
2321                         IsDlgButtonChecked(hwnd, IDC_X11_FORWARD);
2322                 break;
2323               case IDC_X11_DISPLAY:
2324                 if (HIWORD(wParam) == EN_CHANGE)
2325                     GetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display,
2326                                    sizeof(cfg.x11_display) - 1);
2327                 break;
2328             }
2329         return 0;
2330       case WM_CLOSE:
2331         EndDialog(hwnd, 0);
2332         return 0;
2333
2334         /* Grrr Explorer will maximize Dialogs! */
2335       case WM_SIZE:
2336         if (wParam == SIZE_MAXIMIZED)
2337             force_normal(hwnd);
2338         return 0;
2339     }
2340     return 0;
2341 }
2342
2343 static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
2344                                 WPARAM wParam, LPARAM lParam)
2345 {
2346     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2347     }
2348     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2349         EnableWindow(hwnd, 0);
2350         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2351                   GetParent(hwnd), AboutProc);
2352         EnableWindow(hwnd, 1);
2353         SetActiveWindow(hwnd);
2354     }
2355     return GenericMainDlgProc(hwnd, msg, wParam, lParam, 0);
2356 }
2357
2358 static int CALLBACK ReconfDlgProc(HWND hwnd, UINT msg,
2359                                   WPARAM wParam, LPARAM lParam)
2360 {
2361     return GenericMainDlgProc(hwnd, msg, wParam, lParam, 1);
2362 }
2363
2364 void defuse_showwindow(void)
2365 {
2366     /*
2367      * Work around the fact that the app's first call to ShowWindow
2368      * will ignore the default in favour of the shell-provided
2369      * setting.
2370      */
2371     {
2372         HWND hwnd;
2373         hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2374                             NULL, NullDlgProc);
2375         ShowWindow(hwnd, SW_HIDE);
2376         DestroyWindow(hwnd);
2377     }
2378 }
2379
2380 int do_config(void)
2381 {
2382     int ret;
2383
2384     get_sesslist(TRUE);
2385     savedsession[0] = '\0';
2386     ret =
2387         DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2388     get_sesslist(FALSE);
2389
2390     return ret;
2391 }
2392
2393 int do_reconfig(HWND hwnd)
2394 {
2395     Config backup_cfg;
2396     int ret;
2397
2398     backup_cfg = cfg;                  /* structure copy */
2399     ret =
2400         DialogBox(hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2401     if (!ret)
2402         cfg = backup_cfg;              /* structure copy */
2403
2404     return ret;
2405 }
2406
2407 void logevent(char *string)
2408 {
2409     char timebuf[40];
2410     time_t t;
2411
2412     if (nevents >= negsize) {
2413         negsize += 64;
2414         events = srealloc(events, negsize * sizeof(*events));
2415     }
2416
2417     time(&t);
2418     strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t",
2419              localtime(&t));
2420
2421     events[nevents] = smalloc(strlen(timebuf) + strlen(string) + 1);
2422     strcpy(events[nevents], timebuf);
2423     strcat(events[nevents], string);
2424     if (logbox) {
2425         int count;
2426         SendDlgItemMessage(logbox, IDN_LIST, LB_ADDSTRING,
2427                            0, (LPARAM) events[nevents]);
2428         count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2429         SendDlgItemMessage(logbox, IDN_LIST, LB_SETTOPINDEX, count - 1, 0);
2430     }
2431     nevents++;
2432 }
2433
2434 void showeventlog(HWND hwnd)
2435 {
2436     if (!logbox) {
2437         logbox = CreateDialog(hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2438                               hwnd, LogProc);
2439         ShowWindow(logbox, SW_SHOWNORMAL);
2440     }
2441     SetActiveWindow(logbox);
2442 }
2443
2444 void showabout(HWND hwnd)
2445 {
2446     DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
2447 }
2448
2449 void verify_ssh_host_key(char *host, int port, char *keytype,
2450                          char *keystr, char *fingerprint)
2451 {
2452     int ret;
2453
2454     static const char absentmsg[] =
2455         "The server's host key is not cached in the registry. You\n"
2456         "have no guarantee that the server is the computer you\n"
2457         "think it is.\n"
2458         "The server's key fingerprint is:\n"
2459         "%s\n"
2460         "If you trust this host, hit Yes to add the key to\n"
2461         "PuTTY's cache and carry on connecting.\n"
2462         "If you do not trust this host, hit No to abandon the\n"
2463         "connection.\n";
2464
2465     static const char wrongmsg[] =
2466         "WARNING - POTENTIAL SECURITY BREACH!\n"
2467         "\n"
2468         "The server's host key does not match the one PuTTY has\n"
2469         "cached in the registry. This means that either the\n"
2470         "server administrator has changed the host key, or you\n"
2471         "have actually connected to another computer pretending\n"
2472         "to be the server.\n"
2473         "The new key fingerprint is:\n"
2474         "%s\n"
2475         "If you were expecting this change and trust the new key,\n"
2476         "hit Yes to update PuTTY's cache and continue connecting.\n"
2477         "If you want to carry on connecting but without updating\n"
2478         "the cache, hit No.\n"
2479         "If you want to abandon the connection completely, hit\n"
2480         "Cancel. Hitting Cancel is the ONLY guaranteed safe\n" "choice.\n";
2481
2482     static const char mbtitle[] = "PuTTY Security Alert";
2483
2484
2485     char message[160 +
2486                  /* sensible fingerprint max size */
2487         (sizeof(absentmsg) > sizeof(wrongmsg) ?
2488          sizeof(absentmsg) : sizeof(wrongmsg))];
2489
2490     /*
2491      * Verify the key against the registry.
2492      */
2493     ret = verify_host_key(host, port, keytype, keystr);
2494
2495     if (ret == 0)                      /* success - key matched OK */
2496         return;
2497     if (ret == 2) {                    /* key was different */
2498         int mbret;
2499         sprintf(message, wrongmsg, fingerprint);
2500         mbret = MessageBox(NULL, message, mbtitle,
2501                            MB_ICONWARNING | MB_YESNOCANCEL);
2502         if (mbret == IDYES)
2503             store_host_key(host, port, keytype, keystr);
2504         if (mbret == IDCANCEL)
2505             exit(0);
2506     }
2507     if (ret == 1) {                    /* key was absent */
2508         int mbret;
2509         sprintf(message, absentmsg, fingerprint);
2510         mbret = MessageBox(NULL, message, mbtitle,
2511                            MB_ICONWARNING | MB_YESNO);
2512         if (mbret == IDNO)
2513             exit(0);
2514         store_host_key(host, port, keytype, keystr);
2515     }
2516 }
2517
2518 /*
2519  * Ask whether to wipe a session log file before writing to it.
2520  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2521  */
2522 int askappend(char *filename)
2523 {
2524     static const char mbtitle[] = "PuTTY Log to File";
2525     static const char msgtemplate[] =
2526         "The session log file \"%.*s\" already exists.\n"
2527         "You can overwrite it with a new session log,\n"
2528         "append your session log to the end of it,\n"
2529         "or disable session logging for this session.\n"
2530         "Hit Yes to wipe the file, No to append to it,\n"
2531         "or Cancel to disable logging.";
2532     char message[sizeof(msgtemplate) + FILENAME_MAX];
2533     int mbret;
2534     if (cfg.logxfovr != LGXF_ASK) {
2535         return ((cfg.logxfovr == LGXF_OVR) ? 2 : 1);
2536     }
2537     sprintf(message, msgtemplate, FILENAME_MAX, filename);
2538
2539     mbret = MessageBox(NULL, message, mbtitle,
2540                        MB_ICONQUESTION | MB_YESNOCANCEL);
2541     if (mbret == IDYES)
2542         return 2;
2543     else if (mbret == IDNO)
2544         return 1;
2545     else
2546         return 0;
2547 }