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