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