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