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