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