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