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