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