]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
RDB's Unicode patch. Fonts are now used in Unicode mode where
[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         /*
1219          * Centre the window.
1220          */
1221         {                              /* centre the window */
1222             RECT rs, rd;
1223
1224             hw = GetDesktopWindow();
1225             if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))
1226                 MoveWindow(hwnd,
1227                            (rs.right + rs.left + rd.left - rd.right) / 2,
1228                            (rs.bottom + rs.top + rd.top - rd.bottom) / 2,
1229                            rd.right - rd.left, rd.bottom - rd.top, TRUE);
1230         }
1231
1232         /*
1233          * Create the tree view.
1234          */
1235         {
1236             RECT r;
1237             WPARAM font;
1238             HWND tvstatic;
1239
1240             r.left = 3;
1241             r.right = r.left + 75;
1242             r.top = 3;
1243             r.bottom = r.top + 10;
1244             MapDialogRect(hwnd, &r);
1245             tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1246                                       WS_CHILD | WS_VISIBLE,
1247                                       r.left, r.top,
1248                                       r.right - r.left, r.bottom - r.top,
1249                                       hwnd, (HMENU) IDCX_TVSTATIC, hinst,
1250                                       NULL);
1251             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1252             SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1253
1254             r.left = 3;
1255             r.right = r.left + 75;
1256             r.top = 13;
1257             r.bottom = r.top + 206;
1258             MapDialogRect(hwnd, &r);
1259             treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1260                                       WS_CHILD | WS_VISIBLE |
1261                                       WS_TABSTOP | TVS_HASLINES |
1262                                       TVS_DISABLEDRAGDROP | TVS_HASBUTTONS
1263                                       | TVS_LINESATROOT |
1264                                       TVS_SHOWSELALWAYS, r.left, r.top,
1265                                       r.right - r.left, r.bottom - r.top,
1266                                       hwnd, (HMENU) IDCX_TREEVIEW, hinst,
1267                                       NULL);
1268             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1269             SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1270             tvfaff.treeview = treeview;
1271             memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1272         }
1273
1274         /*
1275          * Set up the tree view contents.
1276          */
1277         hsession = treeview_insert(&tvfaff, 0, "Session");
1278         treeview_insert(&tvfaff, 1, "Logging");
1279         treeview_insert(&tvfaff, 0, "Terminal");
1280         treeview_insert(&tvfaff, 1, "Keyboard");
1281         treeview_insert(&tvfaff, 1, "Bell");
1282         treeview_insert(&tvfaff, 0, "Window");
1283         treeview_insert(&tvfaff, 1, "Appearance");
1284         treeview_insert(&tvfaff, 1, "Translation");
1285         treeview_insert(&tvfaff, 1, "Selection");
1286         treeview_insert(&tvfaff, 1, "Colours");
1287         treeview_insert(&tvfaff, 0, "Connection");
1288         if (dlgtype == 0) {
1289             treeview_insert(&tvfaff, 1, "Telnet");
1290             treeview_insert(&tvfaff, 1, "Rlogin");
1291             if (backends[3].backend != NULL) {
1292                 treeview_insert(&tvfaff, 1, "SSH");
1293                 treeview_insert(&tvfaff, 2, "Tunnels");
1294             }
1295         }
1296
1297         /*
1298          * Put the treeview selection on to the Session panel. This
1299          * should also cause creation of the relevant controls.
1300          */
1301         TreeView_SelectItem(treeview, hsession);
1302
1303         /*
1304          * Set focus into the first available control.
1305          */
1306         {
1307             HWND ctl;
1308             ctl = GetDlgItem(hwnd, IDC_HOST);
1309             if (!ctl)
1310                 ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1311             SetFocus(ctl);
1312         }
1313
1314         SetWindowLong(hwnd, GWL_USERDATA, 1);
1315         return 0;
1316       case WM_LBUTTONUP:
1317         /*
1318          * Button release should trigger WM_OK if there was a
1319          * previous double click on the session list.
1320          */
1321         ReleaseCapture();
1322         if (readytogo)
1323             SendMessage(hwnd, WM_COMMAND, IDOK, 0);
1324         break;
1325       case WM_NOTIFY:
1326         if (LOWORD(wParam) == IDCX_TREEVIEW &&
1327             ((LPNMHDR) lParam)->code == TVN_SELCHANGED) {
1328             HTREEITEM i =
1329                 TreeView_GetSelection(((LPNMHDR) lParam)->hwndFrom);
1330             TVITEM item;
1331             int j;
1332             char buffer[64];
1333             item.hItem = i;
1334             item.pszText = buffer;
1335             item.cchTextMax = sizeof(buffer);
1336             item.mask = TVIF_TEXT;
1337             TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &item);
1338             for (j = controlstartvalue; j < controlendvalue; j++) {
1339                 HWND item = GetDlgItem(hwnd, j);
1340                 if (item)
1341                     DestroyWindow(item);
1342             }
1343             if (!strcmp(buffer, "Session"))
1344                 create_controls(hwnd, dlgtype, sessionpanelstart);
1345             if (!strcmp(buffer, "Logging"))
1346                 create_controls(hwnd, dlgtype, loggingpanelstart);
1347             if (!strcmp(buffer, "Keyboard"))
1348                 create_controls(hwnd, dlgtype, keyboardpanelstart);
1349             if (!strcmp(buffer, "Terminal"))
1350                 create_controls(hwnd, dlgtype, terminalpanelstart);
1351             if (!strcmp(buffer, "Bell"))
1352                 create_controls(hwnd, dlgtype, bellpanelstart);
1353             if (!strcmp(buffer, "Window"))
1354                 create_controls(hwnd, dlgtype, windowpanelstart);
1355             if (!strcmp(buffer, "Appearance"))
1356                 create_controls(hwnd, dlgtype, appearancepanelstart);
1357             if (!strcmp(buffer, "Tunnels"))
1358                 create_controls(hwnd, dlgtype, tunnelspanelstart);
1359             if (!strcmp(buffer, "Connection"))
1360                 create_controls(hwnd, dlgtype, connectionpanelstart);
1361             if (!strcmp(buffer, "Telnet"))
1362                 create_controls(hwnd, dlgtype, telnetpanelstart);
1363             if (!strcmp(buffer, "Rlogin"))
1364                 create_controls(hwnd, dlgtype, rloginpanelstart);
1365             if (!strcmp(buffer, "SSH"))
1366                 create_controls(hwnd, dlgtype, sshpanelstart);
1367             if (!strcmp(buffer, "Selection"))
1368                 create_controls(hwnd, dlgtype, selectionpanelstart);
1369             if (!strcmp(buffer, "Colours"))
1370                 create_controls(hwnd, dlgtype, colourspanelstart);
1371             if (!strcmp(buffer, "Translation"))
1372                 create_controls(hwnd, dlgtype, translationpanelstart);
1373
1374             init_dlg_ctrls(hwnd);
1375
1376             SetFocus(((LPNMHDR) lParam)->hwndFrom);     /* ensure focus stays */
1377             return 0;
1378         }
1379         break;
1380       case WM_COMMAND:
1381         /*
1382          * Only process WM_COMMAND once the dialog is fully formed.
1383          */
1384         if (GetWindowLong(hwnd, GWL_USERDATA) == 1)
1385             switch (LOWORD(wParam)) {
1386               case IDOK:
1387                 if (*cfg.host)
1388                     EndDialog(hwnd, 1);
1389                 else
1390                     MessageBeep(0);
1391                 return 0;
1392               case IDCANCEL:
1393                 EndDialog(hwnd, 0);
1394                 return 0;
1395               case IDC_PROTTELNET:
1396               case IDC_PROTRLOGIN:
1397               case IDC_PROTSSH:
1398               case IDC_PROTRAW:
1399                 if (HIWORD(wParam) == BN_CLICKED ||
1400                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1401                     int i = IsDlgButtonChecked(hwnd, IDC_PROTSSH);
1402                     int j = IsDlgButtonChecked(hwnd, IDC_PROTTELNET);
1403                     int k = IsDlgButtonChecked(hwnd, IDC_PROTRLOGIN);
1404                     cfg.protocol =
1405                         i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN :
1406                         PROT_RAW;
1407                     if ((cfg.protocol == PROT_SSH && cfg.port != 22)
1408                         || (cfg.protocol == PROT_TELNET && cfg.port != 23)
1409                         || (cfg.protocol == PROT_RLOGIN
1410                             && cfg.port != 513)) {
1411                         cfg.port = i ? 22 : j ? 23 : 513;
1412                         SetDlgItemInt(hwnd, IDC_PORT, cfg.port, FALSE);
1413                     }
1414                 }
1415                 break;
1416               case IDC_HOST:
1417                 if (HIWORD(wParam) == EN_CHANGE)
1418                     GetDlgItemText(hwnd, IDC_HOST, cfg.host,
1419                                    sizeof(cfg.host) - 1);
1420                 break;
1421               case IDC_PORT:
1422                 if (HIWORD(wParam) == EN_CHANGE) {
1423                     GetDlgItemText(hwnd, IDC_PORT, portname, 31);
1424                     if (isdigit(portname[0]))
1425                         MyGetDlgItemInt(hwnd, IDC_PORT, &cfg.port);
1426                     else {
1427                         service = getservbyname(portname, NULL);
1428                         if (service)
1429                             cfg.port = ntohs(service->s_port);
1430                         else
1431                             cfg.port = 0;
1432                     }
1433                 }
1434                 break;
1435               case IDC_SESSEDIT:
1436                 if (HIWORD(wParam) == EN_CHANGE) {
1437                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1438                                        (WPARAM) - 1, 0);
1439                     GetDlgItemText(hwnd, IDC_SESSEDIT,
1440                                    savedsession, sizeof(savedsession) - 1);
1441                     savedsession[sizeof(savedsession) - 1] = '\0';
1442                 }
1443                 break;
1444               case IDC_SESSSAVE:
1445                 if (HIWORD(wParam) == BN_CLICKED ||
1446                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1447                     /*
1448                      * Save a session
1449                      */
1450                     char str[2048];
1451                     GetDlgItemText(hwnd, IDC_SESSEDIT, str,
1452                                    sizeof(str) - 1);
1453                     if (!*str) {
1454                         int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1455                                                    LB_GETCURSEL, 0, 0);
1456                         if (n == LB_ERR) {
1457                             MessageBeep(0);
1458                             break;
1459                         }
1460                         strcpy(str, sessions[n]);
1461                     }
1462                     save_settings(str, !!strcmp(str, "Default Settings"),
1463                                   &cfg);
1464                     get_sesslist(FALSE);
1465                     get_sesslist(TRUE);
1466                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1467                                        0, 0);
1468                     for (i = 0; i < nsessions; i++)
1469                         SendDlgItemMessage(hwnd, IDC_SESSLIST,
1470                                            LB_ADDSTRING, 0,
1471                                            (LPARAM) (sessions[i]));
1472                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1473                                        (WPARAM) - 1, 0);
1474                 }
1475                 break;
1476               case IDC_SESSLIST:
1477               case IDC_SESSLOAD:
1478                 if (LOWORD(wParam) == IDC_SESSLOAD &&
1479                     HIWORD(wParam) != BN_CLICKED &&
1480                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
1481                 if (LOWORD(wParam) == IDC_SESSLIST &&
1482                     HIWORD(wParam) != LBN_DBLCLK) break;
1483                 {
1484                     int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1485                                                LB_GETCURSEL, 0, 0);
1486                     int isdef;
1487                     if (n == LB_ERR) {
1488                         MessageBeep(0);
1489                         break;
1490                     }
1491                     isdef = !strcmp(sessions[n], "Default Settings");
1492                     load_settings(sessions[n], !isdef, &cfg);
1493                     init_dlg_ctrls(hwnd);
1494                     if (!isdef)
1495                         SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1496                     else
1497                         SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1498                 }
1499                 if (LOWORD(wParam) == IDC_SESSLIST) {
1500                     /*
1501                      * A double-click on a saved session should
1502                      * actually start the session, not just load it.
1503                      * Unless it's Default Settings or some other
1504                      * host-less set of saved settings.
1505                      */
1506                     if (*cfg.host) {
1507                         readytogo = TRUE;
1508                         SetCapture(hwnd);
1509                     }
1510                 }
1511                 break;
1512               case IDC_SESSDEL:
1513                 if (HIWORD(wParam) == BN_CLICKED ||
1514                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1515                     int n = SendDlgItemMessage(hwnd, IDC_SESSLIST,
1516                                                LB_GETCURSEL, 0, 0);
1517                     if (n == LB_ERR || n == 0) {
1518                         MessageBeep(0);
1519                         break;
1520                     }
1521                     del_settings(sessions[n]);
1522                     get_sesslist(FALSE);
1523                     get_sesslist(TRUE);
1524                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1525                                        0, 0);
1526                     for (i = 0; i < nsessions; i++)
1527                         SendDlgItemMessage(hwnd, IDC_SESSLIST,
1528                                            LB_ADDSTRING, 0,
1529                                            (LPARAM) (sessions[i]));
1530                     SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
1531                                        (WPARAM) - 1, 0);
1532                 }
1533               case IDC_PINGEDIT:
1534                 if (HIWORD(wParam) == EN_CHANGE)
1535                     MyGetDlgItemInt(hwnd, IDC_PINGEDIT,
1536                                     &cfg.ping_interval);
1537                 break;
1538               case IDC_DEL008:
1539               case IDC_DEL127:
1540                 if (HIWORD(wParam) == BN_CLICKED ||
1541                     HIWORD(wParam) == BN_DOUBLECLICKED)
1542                         cfg.bksp_is_delete =
1543                         IsDlgButtonChecked(hwnd, IDC_DEL127);
1544                 break;
1545               case IDC_HOMETILDE:
1546               case IDC_HOMERXVT:
1547                 if (HIWORD(wParam) == BN_CLICKED ||
1548                     HIWORD(wParam) == BN_DOUBLECLICKED)
1549                         cfg.rxvt_homeend =
1550                         IsDlgButtonChecked(hwnd, IDC_HOMERXVT);
1551                 break;
1552               case IDC_FUNCTILDE:
1553               case IDC_FUNCLINUX:
1554               case IDC_FUNCXTERM:
1555               case IDC_FUNCVT400:
1556               case IDC_FUNCVT100P:
1557               case IDC_FUNCSCO:
1558                 if (HIWORD(wParam) == BN_CLICKED ||
1559                     HIWORD(wParam) == BN_DOUBLECLICKED)
1560                         switch (LOWORD(wParam)) {
1561                       case IDC_FUNCTILDE:
1562                         cfg.funky_type = 0;
1563                         break;
1564                       case IDC_FUNCLINUX:
1565                         cfg.funky_type = 1;
1566                         break;
1567                       case IDC_FUNCXTERM:
1568                         cfg.funky_type = 2;
1569                         break;
1570                       case IDC_FUNCVT400:
1571                         cfg.funky_type = 3;
1572                         break;
1573                       case IDC_FUNCVT100P:
1574                         cfg.funky_type = 4;
1575                         break;
1576                       case IDC_FUNCSCO:
1577                         cfg.funky_type = 5;
1578                         break;
1579                     }
1580                 break;
1581               case IDC_KPNORMAL:
1582               case IDC_KPAPPLIC:
1583                 if (HIWORD(wParam) == BN_CLICKED ||
1584                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1585                     cfg.app_keypad =
1586                         IsDlgButtonChecked(hwnd, IDC_KPAPPLIC);
1587                     cfg.nethack_keypad = FALSE;
1588                 }
1589                 break;
1590               case IDC_KPNH:
1591                 if (HIWORD(wParam) == BN_CLICKED ||
1592                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1593                     cfg.app_keypad = FALSE;
1594                     cfg.nethack_keypad = TRUE;
1595                 }
1596                 break;
1597               case IDC_CURNORMAL:
1598               case IDC_CURAPPLIC:
1599                 if (HIWORD(wParam) == BN_CLICKED ||
1600                     HIWORD(wParam) == BN_DOUBLECLICKED)
1601                         cfg.app_cursor =
1602                         IsDlgButtonChecked(hwnd, IDC_CURAPPLIC);
1603                 break;
1604               case IDC_NOAPPLICC:
1605                 if (HIWORD(wParam) == BN_CLICKED ||
1606                     HIWORD(wParam) == BN_DOUBLECLICKED)
1607                         cfg.no_applic_c =
1608                         IsDlgButtonChecked(hwnd, IDC_NOAPPLICC);
1609                 break;
1610               case IDC_NOAPPLICK:
1611                 if (HIWORD(wParam) == BN_CLICKED ||
1612                     HIWORD(wParam) == BN_DOUBLECLICKED)
1613                         cfg.no_applic_k =
1614                         IsDlgButtonChecked(hwnd, IDC_NOAPPLICK);
1615                 break;
1616               case IDC_ALTF4:
1617                 if (HIWORD(wParam) == BN_CLICKED ||
1618                     HIWORD(wParam) == BN_DOUBLECLICKED)
1619                         cfg.alt_f4 = IsDlgButtonChecked(hwnd, IDC_ALTF4);
1620                 break;
1621               case IDC_ALTSPACE:
1622                 if (HIWORD(wParam) == BN_CLICKED ||
1623                     HIWORD(wParam) == BN_DOUBLECLICKED)
1624                         cfg.alt_space =
1625                         IsDlgButtonChecked(hwnd, IDC_ALTSPACE);
1626                 break;
1627               case IDC_ALTONLY:
1628                 if (HIWORD(wParam) == BN_CLICKED ||
1629                     HIWORD(wParam) == BN_DOUBLECLICKED)
1630                         cfg.alt_only =
1631                         IsDlgButtonChecked(hwnd, IDC_ALTONLY);
1632                 break;
1633               case IDC_ECHOBACKEND:
1634               case IDC_ECHOYES:
1635               case IDC_ECHONO:
1636                 if (HIWORD(wParam) == BN_CLICKED ||
1637                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1638                     if (LOWORD(wParam) == IDC_ECHOBACKEND)
1639                         cfg.localecho = LD_BACKEND;
1640                     if (LOWORD(wParam) == IDC_ECHOYES)
1641                         cfg.localecho = LD_YES;
1642                     if (LOWORD(wParam) == IDC_ECHONO)
1643                         cfg.localecho = LD_NO;
1644                 }
1645                 break;
1646               case IDC_EDITBACKEND:
1647               case IDC_EDITYES:
1648               case IDC_EDITNO:
1649                 if (HIWORD(wParam) == BN_CLICKED ||
1650                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1651                     if (LOWORD(wParam) == IDC_EDITBACKEND)
1652                         cfg.localedit = LD_BACKEND;
1653                     if (LOWORD(wParam) == IDC_EDITYES)
1654                         cfg.localedit = LD_YES;
1655                     if (LOWORD(wParam) == IDC_EDITNO)
1656                         cfg.localedit = LD_NO;
1657                 }
1658                 break;
1659               case IDC_ANSWEREDIT:
1660                 if (HIWORD(wParam) == EN_CHANGE)
1661                     GetDlgItemText(hwnd, IDC_ANSWEREDIT, cfg.answerback,
1662                                    sizeof(cfg.answerback) - 1);
1663                 break;
1664               case IDC_ALWAYSONTOP:
1665                 if (HIWORD(wParam) == BN_CLICKED ||
1666                     HIWORD(wParam) == BN_DOUBLECLICKED)
1667                         cfg.alwaysontop =
1668                         IsDlgButtonChecked(hwnd, IDC_ALWAYSONTOP);
1669                 break;
1670               case IDC_SCROLLKEY:
1671                 if (HIWORD(wParam) == BN_CLICKED ||
1672                     HIWORD(wParam) == BN_DOUBLECLICKED)
1673                         cfg.scroll_on_key =
1674                         IsDlgButtonChecked(hwnd, IDC_SCROLLKEY);
1675                 break;
1676               case IDC_SCROLLDISP:
1677                 if (HIWORD(wParam) == BN_CLICKED ||
1678                     HIWORD(wParam) == BN_DOUBLECLICKED)
1679                         cfg.scroll_on_disp =
1680                         IsDlgButtonChecked(hwnd, IDC_SCROLLDISP);
1681                 break;
1682               case IDC_COMPOSEKEY:
1683                 if (HIWORD(wParam) == BN_CLICKED ||
1684                     HIWORD(wParam) == BN_DOUBLECLICKED)
1685                         cfg.compose_key =
1686                         IsDlgButtonChecked(hwnd, IDC_COMPOSEKEY);
1687                 break;
1688               case IDC_CTRLALTKEYS:
1689                 if (HIWORD(wParam) == BN_CLICKED ||
1690                     HIWORD(wParam) == BN_DOUBLECLICKED)
1691                         cfg.ctrlaltkeys =
1692                         IsDlgButtonChecked(hwnd, IDC_CTRLALTKEYS);
1693                 break;
1694               case IDC_TELNETKEY:
1695                 if (HIWORD(wParam) == BN_CLICKED ||
1696                     HIWORD(wParam) == BN_DOUBLECLICKED)
1697                         cfg.telnet_keyboard =
1698                         IsDlgButtonChecked(hwnd, IDC_TELNETKEY);
1699                 break;
1700               case IDC_WRAPMODE:
1701                 if (HIWORD(wParam) == BN_CLICKED ||
1702                     HIWORD(wParam) == BN_DOUBLECLICKED)
1703                         cfg.wrap_mode =
1704                         IsDlgButtonChecked(hwnd, IDC_WRAPMODE);
1705                 break;
1706               case IDC_DECOM:
1707                 if (HIWORD(wParam) == BN_CLICKED ||
1708                     HIWORD(wParam) == BN_DOUBLECLICKED)
1709                         cfg.dec_om = IsDlgButtonChecked(hwnd, IDC_DECOM);
1710                 break;
1711               case IDC_LFHASCR:
1712                 if (HIWORD(wParam) == BN_CLICKED ||
1713                     HIWORD(wParam) == BN_DOUBLECLICKED)
1714                         cfg.lfhascr =
1715                         IsDlgButtonChecked(hwnd, IDC_LFHASCR);
1716                 break;
1717               case IDC_ROWSEDIT:
1718                 if (HIWORD(wParam) == EN_CHANGE)
1719                     MyGetDlgItemInt(hwnd, IDC_ROWSEDIT, &cfg.height);
1720                 break;
1721               case IDC_COLSEDIT:
1722                 if (HIWORD(wParam) == EN_CHANGE)
1723                     MyGetDlgItemInt(hwnd, IDC_COLSEDIT, &cfg.width);
1724                 break;
1725               case IDC_SAVEEDIT:
1726                 if (HIWORD(wParam) == EN_CHANGE)
1727                     MyGetDlgItemInt(hwnd, IDC_SAVEEDIT, &cfg.savelines);
1728                 break;
1729               case IDC_CHOOSEFONT:
1730                 {
1731                     HDC hdc = GetDC(0);
1732                     lf.lfHeight = -MulDiv(cfg.fontheight,
1733                                           GetDeviceCaps(hdc, LOGPIXELSY),
1734                                           72);
1735                     ReleaseDC(0, hdc);
1736                 }
1737                 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1738                 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1739                 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1740                 lf.lfCharSet = cfg.fontcharset;
1741                 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1742                 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1743                 lf.lfQuality = DEFAULT_QUALITY;
1744                 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1745                 strncpy(lf.lfFaceName, cfg.font,
1746                         sizeof(lf.lfFaceName) - 1);
1747                 lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
1748
1749                 cf.lStructSize = sizeof(cf);
1750                 cf.hwndOwner = hwnd;
1751                 cf.lpLogFont = &lf;
1752                 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1753                     CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1754
1755                 if (ChooseFont(&cf)) {
1756                     strncpy(cfg.font, lf.lfFaceName, sizeof(cfg.font) - 1);
1757                     cfg.font[sizeof(cfg.font) - 1] = '\0';
1758                     cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1759                     cfg.fontcharset = lf.lfCharSet;
1760                     cfg.fontheight = cf.iPointSize / 10;
1761                     fmtfont(fontstatic);
1762                     SetDlgItemText(hwnd, IDC_FONTSTATIC, fontstatic);
1763                 }
1764                 break;
1765               case IDC_BELL_DISABLED:
1766               case IDC_BELL_DEFAULT:
1767               case IDC_BELL_WAVEFILE:
1768               case IDC_BELL_VISUAL:
1769                 if (HIWORD(wParam) == BN_CLICKED ||
1770                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1771                     if (LOWORD(wParam) == IDC_BELL_DISABLED)
1772                         cfg.beep = BELL_DISABLED;
1773                     if (LOWORD(wParam) == IDC_BELL_DEFAULT)
1774                         cfg.beep = BELL_DEFAULT;
1775                     if (LOWORD(wParam) == IDC_BELL_WAVEFILE)
1776                         cfg.beep = BELL_WAVEFILE;
1777                     if (LOWORD(wParam) == IDC_BELL_VISUAL)
1778                         cfg.beep = BELL_VISUAL;
1779                 }
1780                 break;
1781               case IDC_BELL_WAVEBROWSE:
1782                 memset(&of, 0, sizeof(of));
1783 #ifdef OPENFILENAME_SIZE_VERSION_400
1784                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1785 #else
1786                 of.lStructSize = sizeof(of);
1787 #endif
1788                 of.hwndOwner = hwnd;
1789                 of.lpstrFilter = "Wave Files\0*.WAV\0AllFiles\0*\0\0\0";
1790                 of.lpstrCustomFilter = NULL;
1791                 of.nFilterIndex = 1;
1792                 of.lpstrFile = filename;
1793                 strcpy(filename, cfg.bell_wavefile);
1794                 of.nMaxFile = sizeof(filename);
1795                 of.lpstrFileTitle = NULL;
1796                 of.lpstrInitialDir = NULL;
1797                 of.lpstrTitle = "Select Bell Sound File";
1798                 of.Flags = 0;
1799                 if (GetOpenFileName(&of)) {
1800                     strcpy(cfg.bell_wavefile, filename);
1801                     SetDlgItemText(hwnd, IDC_BELL_WAVEEDIT,
1802                                    cfg.bell_wavefile);
1803                 }
1804                 break;
1805               case IDC_BELL_WAVEEDIT:
1806                 if (HIWORD(wParam) == EN_CHANGE)
1807                     GetDlgItemText(hwnd, IDC_BELL_WAVEEDIT,
1808                                    cfg.bell_wavefile,
1809                                    sizeof(cfg.bell_wavefile) - 1);
1810                 break;
1811               case IDC_BELLOVL:
1812                 if (HIWORD(wParam) == BN_CLICKED ||
1813                     HIWORD(wParam) == BN_DOUBLECLICKED)
1814                         cfg.bellovl =
1815                         IsDlgButtonChecked(hwnd, IDC_BELLOVL);
1816                 break;
1817               case IDC_BELLOVLN:
1818                 if (HIWORD(wParam) == EN_CHANGE)
1819                     MyGetDlgItemInt(hwnd, IDC_BELLOVLN, &cfg.bellovl_n);
1820                 break;
1821               case IDC_BELLOVLT:
1822                 if (HIWORD(wParam) == EN_CHANGE)
1823                     MyGetDlgItemFlt(hwnd, IDC_BELLOVLT, &cfg.bellovl_t,
1824                                     1000);
1825                 break;
1826               case IDC_BELLOVLS:
1827                 if (HIWORD(wParam) == EN_CHANGE)
1828                     MyGetDlgItemFlt(hwnd, IDC_BELLOVLS, &cfg.bellovl_s,
1829                                     1000);
1830                 break;
1831               case IDC_BLINKTEXT:
1832                 if (HIWORD(wParam) == BN_CLICKED ||
1833                     HIWORD(wParam) == BN_DOUBLECLICKED)
1834                         cfg.blinktext =
1835                         IsDlgButtonChecked(hwnd, IDC_BLINKTEXT);
1836                 break;
1837               case IDC_BCE:
1838                 if (HIWORD(wParam) == BN_CLICKED ||
1839                     HIWORD(wParam) == BN_DOUBLECLICKED)
1840                         cfg.bce = IsDlgButtonChecked(hwnd, IDC_BCE);
1841                 break;
1842               case IDC_WINNAME:
1843                 if (HIWORD(wParam) == BN_CLICKED ||
1844                     HIWORD(wParam) == BN_DOUBLECLICKED)
1845                         cfg.win_name_always =
1846                         IsDlgButtonChecked(hwnd, IDC_WINNAME);
1847                 break;
1848               case IDC_HIDEMOUSE:
1849                 if (HIWORD(wParam) == BN_CLICKED ||
1850                     HIWORD(wParam) == BN_DOUBLECLICKED)
1851                         cfg.hide_mouseptr =
1852                         IsDlgButtonChecked(hwnd, IDC_HIDEMOUSE);
1853                 break;
1854               case IDC_SUNKENEDGE:
1855                 if (HIWORD(wParam) == BN_CLICKED ||
1856                     HIWORD(wParam) == BN_DOUBLECLICKED)
1857                         cfg.sunken_edge =
1858                         IsDlgButtonChecked(hwnd, IDC_SUNKENEDGE);
1859                 break;
1860               case IDC_CURBLOCK:
1861                 if (HIWORD(wParam) == BN_CLICKED ||
1862                     HIWORD(wParam) == BN_DOUBLECLICKED)
1863                         cfg.cursor_type = 0;
1864                 break;
1865               case IDC_CURUNDER:
1866                 if (HIWORD(wParam) == BN_CLICKED ||
1867                     HIWORD(wParam) == BN_DOUBLECLICKED)
1868                         cfg.cursor_type = 1;
1869                 break;
1870               case IDC_CURVERT:
1871                 if (HIWORD(wParam) == BN_CLICKED ||
1872                     HIWORD(wParam) == BN_DOUBLECLICKED)
1873                         cfg.cursor_type = 2;
1874                 break;
1875               case IDC_BLINKCUR:
1876                 if (HIWORD(wParam) == BN_CLICKED ||
1877                     HIWORD(wParam) == BN_DOUBLECLICKED)
1878                         cfg.blink_cur =
1879                         IsDlgButtonChecked(hwnd, IDC_BLINKCUR);
1880                 break;
1881               case IDC_SCROLLBAR:
1882                 if (HIWORD(wParam) == BN_CLICKED ||
1883                     HIWORD(wParam) == BN_DOUBLECLICKED)
1884                         cfg.scrollbar =
1885                         IsDlgButtonChecked(hwnd, IDC_SCROLLBAR);
1886                 break;
1887               case IDC_LOCKSIZE:
1888                 if (HIWORD(wParam) == BN_CLICKED ||
1889                     HIWORD(wParam) == BN_DOUBLECLICKED)
1890                         cfg.locksize =
1891                         IsDlgButtonChecked(hwnd, IDC_LOCKSIZE);
1892                 break;
1893               case IDC_WINEDIT:
1894                 if (HIWORD(wParam) == EN_CHANGE)
1895                     GetDlgItemText(hwnd, IDC_WINEDIT, cfg.wintitle,
1896                                    sizeof(cfg.wintitle) - 1);
1897                 break;
1898               case IDC_COEALWAYS:
1899               case IDC_COENEVER:
1900               case IDC_COENORMAL:
1901                 if (HIWORD(wParam) == BN_CLICKED ||
1902                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1903                     cfg.close_on_exit =
1904                         IsDlgButtonChecked(hwnd,
1905                                            IDC_COEALWAYS) ? COE_ALWAYS :
1906                         IsDlgButtonChecked(hwnd,
1907                                            IDC_COENEVER) ? COE_NEVER :
1908                         COE_NORMAL;
1909                 }
1910                 break;
1911               case IDC_CLOSEWARN:
1912                 if (HIWORD(wParam) == BN_CLICKED ||
1913                     HIWORD(wParam) == BN_DOUBLECLICKED)
1914                         cfg.warn_on_close =
1915                         IsDlgButtonChecked(hwnd, IDC_CLOSEWARN);
1916                 break;
1917               case IDC_TTEDIT:
1918                 if (HIWORD(wParam) == EN_CHANGE)
1919                     GetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype,
1920                                    sizeof(cfg.termtype) - 1);
1921                 break;
1922               case IDC_LGFEDIT:
1923                 if (HIWORD(wParam) == EN_CHANGE)
1924                     GetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename,
1925                                    sizeof(cfg.logfilename) - 1);
1926                 break;
1927               case IDC_LGFBUTTON:
1928                 memset(&of, 0, sizeof(of));
1929 #ifdef OPENFILENAME_SIZE_VERSION_400
1930                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1931 #else
1932                 of.lStructSize = sizeof(of);
1933 #endif
1934                 of.hwndOwner = hwnd;
1935                 of.lpstrFilter = "All Files\0*\0\0\0";
1936                 of.lpstrCustomFilter = NULL;
1937                 of.nFilterIndex = 1;
1938                 of.lpstrFile = filename;
1939                 strcpy(filename, cfg.logfilename);
1940                 of.nMaxFile = sizeof(filename);
1941                 of.lpstrFileTitle = NULL;
1942                 of.lpstrInitialDir = NULL;
1943                 of.lpstrTitle = "Select session log file";
1944                 of.Flags = 0;
1945                 if (GetSaveFileName(&of)) {
1946                     strcpy(cfg.logfilename, filename);
1947                     SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
1948                 }
1949                 break;
1950               case IDC_LSTATOFF:
1951               case IDC_LSTATASCII:
1952               case IDC_LSTATRAW:
1953                 if (HIWORD(wParam) == BN_CLICKED ||
1954                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1955                     if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF))
1956                         cfg.logtype = 0;
1957                     if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII))
1958                         cfg.logtype = 1;
1959                     if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW))
1960                         cfg.logtype = 2;
1961                 }
1962                 break;
1963               case IDC_LSTATXASK:
1964               case IDC_LSTATXAPN:
1965               case IDC_LSTATXOVR:
1966                 if (HIWORD(wParam) == BN_CLICKED ||
1967                     HIWORD(wParam) == BN_DOUBLECLICKED) {
1968                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXASK))
1969                         cfg.logxfovr = LGXF_ASK;
1970                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXAPN))
1971                         cfg.logxfovr = LGXF_APN;
1972                     if (IsDlgButtonChecked(hwnd, IDC_LSTATXOVR))
1973                         cfg.logxfovr = LGXF_OVR;
1974                 }
1975                 break;
1976               case IDC_TSEDIT:
1977               case IDC_R_TSEDIT:
1978                 if (HIWORD(wParam) == EN_CHANGE)
1979                     GetDlgItemText(hwnd, LOWORD(wParam), cfg.termspeed,
1980                                    sizeof(cfg.termspeed) - 1);
1981                 break;
1982               case IDC_LOGEDIT:
1983                 if (HIWORD(wParam) == EN_CHANGE)
1984                     GetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username,
1985                                    sizeof(cfg.username) - 1);
1986                 break;
1987               case IDC_RLLUSEREDIT:
1988                 if (HIWORD(wParam) == EN_CHANGE)
1989                     GetDlgItemText(hwnd, IDC_RLLUSEREDIT,
1990                                    cfg.localusername,
1991                                    sizeof(cfg.localusername) - 1);
1992                 break;
1993               case IDC_EMBSD:
1994               case IDC_EMRFC:
1995                 cfg.rfc_environ = IsDlgButtonChecked(hwnd, IDC_EMRFC);
1996                 break;
1997               case IDC_TPASSIVE:
1998               case IDC_TACTIVE:
1999                 cfg.passive_telnet =
2000                     IsDlgButtonChecked(hwnd, IDC_TPASSIVE);
2001                 break;
2002               case IDC_ENVADD:
2003                 if (HIWORD(wParam) == BN_CLICKED ||
2004                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2005                     char str[sizeof(cfg.environmt)];
2006                     char *p;
2007                     GetDlgItemText(hwnd, IDC_VAREDIT, str,
2008                                    sizeof(str) - 1);
2009                     if (!*str) {
2010                         MessageBeep(0);
2011                         break;
2012                     }
2013                     p = str + strlen(str);
2014                     *p++ = '\t';
2015                     GetDlgItemText(hwnd, IDC_VALEDIT, p,
2016                                    sizeof(str) - 1 - (p - str));
2017                     if (!*p) {
2018                         MessageBeep(0);
2019                         break;
2020                     }
2021                     p = cfg.environmt;
2022                     while (*p) {
2023                         while (*p)
2024                             p++;
2025                         p++;
2026                     }
2027                     if ((p - cfg.environmt) + strlen(str) + 2 <
2028                         sizeof(cfg.environmt)) {
2029                         strcpy(p, str);
2030                         p[strlen(str) + 1] = '\0';
2031                         SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_ADDSTRING,
2032                                            0, (LPARAM) str);
2033                         SetDlgItemText(hwnd, IDC_VAREDIT, "");
2034                         SetDlgItemText(hwnd, IDC_VALEDIT, "");
2035                     } else {
2036                         MessageBox(hwnd, "Environment too big",
2037                                    "PuTTY Error", MB_OK | MB_ICONERROR);
2038                     }
2039                 }
2040                 break;
2041               case IDC_ENVREMOVE:
2042                 if (HIWORD(wParam) != BN_CLICKED &&
2043                     HIWORD(wParam) != BN_DOUBLECLICKED) break;
2044                 i =
2045                     SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_GETCURSEL, 0,
2046                                        0);
2047                 if (i == LB_ERR)
2048                     MessageBeep(0);
2049                 else {
2050                     char *p, *q;
2051
2052                     SendDlgItemMessage(hwnd, IDC_ENVLIST, LB_DELETESTRING,
2053                                        i, 0);
2054                     p = cfg.environmt;
2055                     while (i > 0) {
2056                         if (!*p)
2057                             goto disaster;
2058                         while (*p)
2059                             p++;
2060                         p++;
2061                         i--;
2062                     }
2063                     q = p;
2064                     if (!*p)
2065                         goto disaster;
2066                     while (*p)
2067                         p++;
2068                     p++;
2069                     while (*p) {
2070                         while (*p)
2071                             *q++ = *p++;
2072                         *q++ = *p++;
2073                     }
2074                     *q = '\0';
2075                   disaster:;
2076                 }
2077                 break;
2078               case IDC_NOPTY:
2079                 if (HIWORD(wParam) == BN_CLICKED ||
2080                     HIWORD(wParam) == BN_DOUBLECLICKED)
2081                         cfg.nopty = IsDlgButtonChecked(hwnd, IDC_NOPTY);
2082                 break;
2083               case IDC_COMPRESS:
2084                 if (HIWORD(wParam) == BN_CLICKED ||
2085                     HIWORD(wParam) == BN_DOUBLECLICKED)
2086                         cfg.compression =
2087                         IsDlgButtonChecked(hwnd, IDC_COMPRESS);
2088                 break;
2089               case IDC_BUGGYMAC:
2090                 if (HIWORD(wParam) == BN_CLICKED ||
2091                     HIWORD(wParam) == BN_DOUBLECLICKED)
2092                         cfg.buggymac =
2093                         IsDlgButtonChecked(hwnd, IDC_BUGGYMAC);
2094                 break;
2095               case IDC_AGENTFWD:
2096                 if (HIWORD(wParam) == BN_CLICKED ||
2097                     HIWORD(wParam) == BN_DOUBLECLICKED)
2098                         cfg.agentfwd =
2099                         IsDlgButtonChecked(hwnd, IDC_AGENTFWD);
2100                 break;
2101               case IDC_CIPHER3DES:
2102               case IDC_CIPHERBLOWF:
2103               case IDC_CIPHERDES:
2104               case IDC_CIPHERAES:
2105                 if (HIWORD(wParam) == BN_CLICKED ||
2106                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2107                     if (IsDlgButtonChecked(hwnd, IDC_CIPHER3DES))
2108                         cfg.cipher = CIPHER_3DES;
2109                     else if (IsDlgButtonChecked(hwnd, IDC_CIPHERBLOWF))
2110                         cfg.cipher = CIPHER_BLOWFISH;
2111                     else if (IsDlgButtonChecked(hwnd, IDC_CIPHERDES))
2112                         cfg.cipher = CIPHER_DES;
2113                     else if (IsDlgButtonChecked(hwnd, IDC_CIPHERAES))
2114                         cfg.cipher = CIPHER_AES;
2115                 }
2116                 break;
2117               case IDC_SSHPROT1:
2118               case IDC_SSHPROT2:
2119                 if (HIWORD(wParam) == BN_CLICKED ||
2120                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2121                     if (IsDlgButtonChecked(hwnd, IDC_SSHPROT1))
2122                         cfg.sshprot = 1;
2123                     else if (IsDlgButtonChecked(hwnd, IDC_SSHPROT2))
2124                         cfg.sshprot = 2;
2125                 }
2126                 break;
2127               case IDC_AUTHTIS:
2128                 if (HIWORD(wParam) == BN_CLICKED ||
2129                     HIWORD(wParam) == BN_DOUBLECLICKED)
2130                         cfg.try_tis_auth =
2131                         IsDlgButtonChecked(hwnd, IDC_AUTHTIS);
2132                 break;
2133               case IDC_PKEDIT:
2134                 if (HIWORD(wParam) == EN_CHANGE)
2135                     GetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile,
2136                                    sizeof(cfg.keyfile) - 1);
2137                 break;
2138               case IDC_CMDEDIT:
2139                 if (HIWORD(wParam) == EN_CHANGE)
2140                     GetDlgItemText(hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2141                                    sizeof(cfg.remote_cmd) - 1);
2142                 break;
2143               case IDC_PKBUTTON:
2144                 memset(&of, 0, sizeof(of));
2145 #ifdef OPENFILENAME_SIZE_VERSION_400
2146                 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2147 #else
2148                 of.lStructSize = sizeof(of);
2149 #endif
2150                 of.hwndOwner = hwnd;
2151                 of.lpstrFilter = "All Files\0*\0\0\0";
2152                 of.lpstrCustomFilter = NULL;
2153                 of.nFilterIndex = 1;
2154                 of.lpstrFile = filename;
2155                 strcpy(filename, cfg.keyfile);
2156                 of.nMaxFile = sizeof(filename);
2157                 of.lpstrFileTitle = NULL;
2158                 of.lpstrInitialDir = NULL;
2159                 of.lpstrTitle = "Select Public Key File";
2160                 of.Flags = 0;
2161                 if (GetOpenFileName(&of)) {
2162                     strcpy(cfg.keyfile, filename);
2163                     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
2164                 }
2165                 break;
2166               case IDC_RAWCNP:
2167                 cfg.rawcnp = IsDlgButtonChecked(hwnd, IDC_RAWCNP);
2168               case IDC_MBWINDOWS:
2169               case IDC_MBXTERM:
2170                 cfg.mouse_is_xterm = IsDlgButtonChecked(hwnd, IDC_MBXTERM);
2171                 break;
2172               case IDC_CCSET:
2173                 {
2174                     BOOL ok;
2175                     int i;
2176                     int n = GetDlgItemInt(hwnd, IDC_CCEDIT, &ok, FALSE);
2177
2178                     if (!ok)
2179                         MessageBeep(0);
2180                     else {
2181                         for (i = 0; i < 128; i++)
2182                             if (SendDlgItemMessage
2183                                 (hwnd, IDC_CCLIST, LB_GETSEL, i, 0)) {
2184                                 char str[100];
2185                                 cfg.wordness[i] = n;
2186                                 SendDlgItemMessage(hwnd, IDC_CCLIST,
2187                                                    LB_DELETESTRING, i, 0);
2188                                 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2189                                         (i >= 0x21 && i != 0x7F) ? i : ' ',
2190                                         cfg.wordness[i]);
2191                                 SendDlgItemMessage(hwnd, IDC_CCLIST,
2192                                                    LB_INSERTSTRING, i,
2193                                                    (LPARAM) str);
2194                             }
2195                     }
2196                 }
2197                 break;
2198               case IDC_BOLDCOLOUR:
2199                 if (HIWORD(wParam) == BN_CLICKED ||
2200                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2201                     int n, i;
2202                     cfg.bold_colour =
2203                         IsDlgButtonChecked(hwnd, IDC_BOLDCOLOUR);
2204                     n =
2205                         SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2206                                            LB_GETCOUNT, 0, 0);
2207                     if (n != 12 + 10 * cfg.bold_colour) {
2208                         for (i = n; i-- > 0;)
2209                             SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2210                                                LB_DELETESTRING, i, 0);
2211                         for (i = 0; i < 22; i++)
2212                             if (cfg.bold_colour || permcolour[i])
2213                                 SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2214                                                    LB_ADDSTRING, 0,
2215                                                    (LPARAM) colours[i]);
2216                     }
2217                 }
2218                 break;
2219               case IDC_PALETTE:
2220                 if (HIWORD(wParam) == BN_CLICKED ||
2221                     HIWORD(wParam) == BN_DOUBLECLICKED)
2222                         cfg.try_palette =
2223                         IsDlgButtonChecked(hwnd, IDC_PALETTE);
2224                 break;
2225               case IDC_COLOURLIST:
2226                 if (HIWORD(wParam) == LBN_DBLCLK ||
2227                     HIWORD(wParam) == LBN_SELCHANGE) {
2228                     int i = SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2229                                                LB_GETCURSEL,
2230                                                0, 0);
2231                     if (!cfg.bold_colour)
2232                         i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
2233                     SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
2234                                   FALSE);
2235                     SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[i][1],
2236                                   FALSE);
2237                     SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[i][2],
2238                                   FALSE);
2239                 }
2240                 break;
2241               case IDC_CHANGE:
2242                 if (HIWORD(wParam) == BN_CLICKED ||
2243                     HIWORD(wParam) == BN_DOUBLECLICKED) {
2244                     static CHOOSECOLOR cc;
2245                     static DWORD custom[16] = { 0 };    /* zero initialisers */
2246                     int i = SendDlgItemMessage(hwnd, IDC_COLOURLIST,
2247                                                LB_GETCURSEL,
2248                                                0, 0);
2249                     if (!cfg.bold_colour)
2250                         i = (i < 3 ? i * 2 : i == 3 ? 5 : i * 2 - 2);
2251                     cc.lStructSize = sizeof(cc);
2252                     cc.hwndOwner = hwnd;
2253                     cc.hInstance = (HWND) hinst;
2254                     cc.lpCustColors = custom;
2255                     cc.rgbResult =
2256                         RGB(cfg.colours[i][0], cfg.colours[i][1],
2257                             cfg.colours[i][2]);
2258                     cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2259                     if (ChooseColor(&cc)) {
2260                         cfg.colours[i][0] =
2261                             (unsigned char) (cc.rgbResult & 0xFF);
2262                         cfg.colours[i][1] =
2263                             (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2264                         cfg.colours[i][2] =
2265                             (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2266                         SetDlgItemInt(hwnd, IDC_RVALUE, cfg.colours[i][0],
2267                                       FALSE);
2268                         SetDlgItemInt(hwnd, IDC_GVALUE, cfg.colours[i][1],
2269                                       FALSE);
2270                         SetDlgItemInt(hwnd, IDC_BVALUE, cfg.colours[i][2],
2271                                       FALSE);
2272                     }
2273                 }
2274                 break;
2275               case IDC_CODEPAGE:
2276                 if (HIWORD(wParam) == EN_CHANGE)
2277                     GetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage,
2278                                    sizeof(cfg.line_codepage) - 1);
2279                 if (HIWORD(wParam) == EN_KILLFOCUS) {
2280                     int cp = decode_codepage(cfg.line_codepage);
2281                     char buf[256];
2282                     if (cp < -1) {
2283                         if (cp == -2)
2284                             sprintf(buf,
2285                                     "Unable to identify character set '%s', "
2286                                     "translation disabled.",
2287                                     cfg.line_codepage);
2288                         if (cp == -3)
2289                             sprintf(buf,
2290                                     "Character set '%s' is a DBCS, "
2291                                     "translation is not available.",
2292                                     cfg.line_codepage);
2293                         MessageBox(hwnd, buf, "PuTTY Error",
2294                                    MB_ICONERROR | MB_OK);
2295                     }
2296                     strcpy(cfg.line_codepage, cp_name(cp));
2297                     SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
2298                 }
2299                 break;
2300               case IDC_VTXWINDOWS:
2301               case IDC_VTOEMANSI:
2302               case IDC_VTOEMONLY:
2303               case IDC_VTPOORMAN:
2304               case IDC_VTUNICODE:
2305                 cfg.vtmode =
2306                     (IsDlgButtonChecked(hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS
2307                      : IsDlgButtonChecked(hwnd,
2308                                           IDC_VTOEMANSI) ? VT_OEMANSI :
2309                      IsDlgButtonChecked(hwnd,
2310                                         IDC_VTOEMONLY) ? VT_OEMONLY :
2311                      IsDlgButtonChecked(hwnd,
2312                                         IDC_VTUNICODE) ? VT_UNICODE :
2313                      VT_POORMAN);
2314                 break;
2315               case IDC_X11_FORWARD:
2316                 if (HIWORD(wParam) == BN_CLICKED ||
2317                     HIWORD(wParam) == BN_DOUBLECLICKED)
2318                         cfg.x11_forward =
2319                         IsDlgButtonChecked(hwnd, IDC_X11_FORWARD);
2320                 break;
2321               case IDC_X11_DISPLAY:
2322                 if (HIWORD(wParam) == EN_CHANGE)
2323                     GetDlgItemText(hwnd, IDC_X11_DISPLAY, cfg.x11_display,
2324                                    sizeof(cfg.x11_display) - 1);
2325                 break;
2326             }
2327         return 0;
2328       case WM_CLOSE:
2329         EndDialog(hwnd, 0);
2330         return 0;
2331
2332         /* Grrr Explorer will maximize Dialogs! */
2333       case WM_SIZE:
2334         if (wParam == SIZE_MAXIMIZED)
2335             force_normal(hwnd);
2336         return 0;
2337     }
2338     return 0;
2339 }
2340
2341 static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
2342                                 WPARAM wParam, LPARAM lParam)
2343 {
2344     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2345     }
2346     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2347         EnableWindow(hwnd, 0);
2348         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2349                   GetParent(hwnd), AboutProc);
2350         EnableWindow(hwnd, 1);
2351         SetActiveWindow(hwnd);
2352     }
2353     return GenericMainDlgProc(hwnd, msg, wParam, lParam, 0);
2354 }
2355
2356 static int CALLBACK ReconfDlgProc(HWND hwnd, UINT msg,
2357                                   WPARAM wParam, LPARAM lParam)
2358 {
2359     return GenericMainDlgProc(hwnd, msg, wParam, lParam, 1);
2360 }
2361
2362 void defuse_showwindow(void)
2363 {
2364     /*
2365      * Work around the fact that the app's first call to ShowWindow
2366      * will ignore the default in favour of the shell-provided
2367      * setting.
2368      */
2369     {
2370         HWND hwnd;
2371         hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2372                             NULL, NullDlgProc);
2373         ShowWindow(hwnd, SW_HIDE);
2374         DestroyWindow(hwnd);
2375     }
2376 }
2377
2378 int do_config(void)
2379 {
2380     int ret;
2381
2382     get_sesslist(TRUE);
2383     savedsession[0] = '\0';
2384     ret =
2385         DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2386     get_sesslist(FALSE);
2387
2388     return ret;
2389 }
2390
2391 int do_reconfig(HWND hwnd)
2392 {
2393     Config backup_cfg;
2394     int ret;
2395
2396     backup_cfg = cfg;                  /* structure copy */
2397     ret =
2398         DialogBox(hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2399     if (!ret)
2400         cfg = backup_cfg;              /* structure copy */
2401
2402     return ret;
2403 }
2404
2405 void logevent(char *string)
2406 {
2407     char timebuf[40];
2408     time_t t;
2409
2410     if (nevents >= negsize) {
2411         negsize += 64;
2412         events = srealloc(events, negsize * sizeof(*events));
2413     }
2414
2415     time(&t);
2416     strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t",
2417              localtime(&t));
2418
2419     events[nevents] = smalloc(strlen(timebuf) + strlen(string) + 1);
2420     strcpy(events[nevents], timebuf);
2421     strcat(events[nevents], string);
2422     if (logbox) {
2423         int count;
2424         SendDlgItemMessage(logbox, IDN_LIST, LB_ADDSTRING,
2425                            0, (LPARAM) events[nevents]);
2426         count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2427         SendDlgItemMessage(logbox, IDN_LIST, LB_SETTOPINDEX, count - 1, 0);
2428     }
2429     nevents++;
2430 }
2431
2432 void showeventlog(HWND hwnd)
2433 {
2434     if (!logbox) {
2435         logbox = CreateDialog(hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2436                               hwnd, LogProc);
2437         ShowWindow(logbox, SW_SHOWNORMAL);
2438     }
2439     SetActiveWindow(logbox);
2440 }
2441
2442 void showabout(HWND hwnd)
2443 {
2444     DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
2445 }
2446
2447 void verify_ssh_host_key(char *host, int port, char *keytype,
2448                          char *keystr, char *fingerprint)
2449 {
2450     int ret;
2451
2452     static const char absentmsg[] =
2453         "The server's host key is not cached in the registry. You\n"
2454         "have no guarantee that the server is the computer you\n"
2455         "think it is.\n"
2456         "The server's key fingerprint is:\n"
2457         "%s\n"
2458         "If you trust this host, hit Yes to add the key to\n"
2459         "PuTTY's cache and carry on connecting.\n"
2460         "If you do not trust this host, hit No to abandon the\n"
2461         "connection.\n";
2462
2463     static const char wrongmsg[] =
2464         "WARNING - POTENTIAL SECURITY BREACH!\n"
2465         "\n"
2466         "The server's host key does not match the one PuTTY has\n"
2467         "cached in the registry. This means that either the\n"
2468         "server administrator has changed the host key, or you\n"
2469         "have actually connected to another computer pretending\n"
2470         "to be the server.\n"
2471         "The new key fingerprint is:\n"
2472         "%s\n"
2473         "If you were expecting this change and trust the new key,\n"
2474         "hit Yes to update PuTTY's cache and continue connecting.\n"
2475         "If you want to carry on connecting but without updating\n"
2476         "the cache, hit No.\n"
2477         "If you want to abandon the connection completely, hit\n"
2478         "Cancel. Hitting Cancel is the ONLY guaranteed safe\n" "choice.\n";
2479
2480     static const char mbtitle[] = "PuTTY Security Alert";
2481
2482
2483     char message[160 +
2484                  /* sensible fingerprint max size */
2485         (sizeof(absentmsg) > sizeof(wrongmsg) ?
2486          sizeof(absentmsg) : sizeof(wrongmsg))];
2487
2488     /*
2489      * Verify the key against the registry.
2490      */
2491     ret = verify_host_key(host, port, keytype, keystr);
2492
2493     if (ret == 0)                      /* success - key matched OK */
2494         return;
2495     if (ret == 2) {                    /* key was different */
2496         int mbret;
2497         sprintf(message, wrongmsg, fingerprint);
2498         mbret = MessageBox(NULL, message, mbtitle,
2499                            MB_ICONWARNING | MB_YESNOCANCEL);
2500         if (mbret == IDYES)
2501             store_host_key(host, port, keytype, keystr);
2502         if (mbret == IDCANCEL)
2503             exit(0);
2504     }
2505     if (ret == 1) {                    /* key was absent */
2506         int mbret;
2507         sprintf(message, absentmsg, fingerprint);
2508         mbret = MessageBox(NULL, message, mbtitle,
2509                            MB_ICONWARNING | MB_YESNO);
2510         if (mbret == IDNO)
2511             exit(0);
2512         store_host_key(host, port, keytype, keystr);
2513     }
2514 }
2515
2516 /*
2517  * Ask whether to wipe a session log file before writing to it.
2518  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2519  */
2520 int askappend(char *filename)
2521 {
2522     static const char mbtitle[] = "PuTTY Log to File";
2523     static const char msgtemplate[] =
2524         "The session log file \"%.*s\" already exists.\n"
2525         "You can overwrite it with a new session log,\n"
2526         "append your session log to the end of it,\n"
2527         "or disable session logging for this session.\n"
2528         "Hit Yes to wipe the file, No to append to it,\n"
2529         "or Cancel to disable logging.";
2530     char message[sizeof(msgtemplate) + FILENAME_MAX];
2531     int mbret;
2532     if (cfg.logxfovr != LGXF_ASK) {
2533         return ((cfg.logxfovr == LGXF_OVR) ? 2 : 1);
2534     }
2535     sprintf(message, msgtemplate, FILENAME_MAX, filename);
2536
2537     mbret = MessageBox(NULL, message, mbtitle,
2538                        MB_ICONQUESTION | MB_YESNOCANCEL);
2539     if (mbret == IDYES)
2540         return 2;
2541     else if (mbret == IDNO)
2542         return 1;
2543     else
2544         return 0;
2545 }