]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
737305dfcb8e7e1ab7ef025da20a37b9b60aaed1
[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 HWND logbox = NULL, abtbox = NULL;
17
18 static int readytogo;
19
20 void force_normal(HWND hwnd)
21 {
22     static int recurse = 0;
23
24     WINDOWPLACEMENT wp;
25
26     if(recurse) return;
27     recurse = 1;
28
29     wp.length = sizeof(wp);
30     if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED)
31     {
32         wp.showCmd = SW_SHOWNORMAL;
33         SetWindowPlacement(hwnd, &wp);
34     }
35     recurse = 0;
36 }
37
38 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
39     BOOL ok;
40     int n;
41     n = GetDlgItemInt (hwnd, id, &ok, FALSE);
42     if (ok)
43         *result = n;
44 }
45
46 static int CALLBACK LogProc (HWND hwnd, UINT msg,
47                              WPARAM wParam, LPARAM lParam) {
48     int i;
49
50     switch (msg) {
51       case WM_INITDIALOG:
52         for (i=0; i<nevents; i++)
53             SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
54                                 0, (LPARAM)events[i]);
55         return 1;
56       case WM_COMMAND:
57         switch (LOWORD(wParam)) {
58           case IDOK:
59             logbox = NULL;
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         DestroyWindow (hwnd);
115         return 0;
116     }
117     return 0;
118 }
119
120 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
121                                  WPARAM wParam, LPARAM lParam) {
122     switch (msg) {
123       case WM_INITDIALOG:
124         return 1;
125       case WM_COMMAND:
126         switch (LOWORD(wParam)) {
127           case IDOK:
128             EndDialog(hwnd, 1);
129             return 0;
130         }
131         return 0;
132       case WM_CLOSE:
133         EndDialog(hwnd, 1);
134         return 0;
135     }
136     return 0;
137 }
138
139 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
140                                WPARAM wParam, LPARAM lParam) {
141     switch (msg) {
142       case WM_INITDIALOG:
143         SetDlgItemText (hwnd, IDA_VERSION, ver);
144         return 1;
145       case WM_COMMAND:
146         switch (LOWORD(wParam)) {
147           case IDOK:
148             abtbox = NULL;
149             DestroyWindow (hwnd);
150             return 0;
151           case IDA_LICENCE:
152             EnableWindow(hwnd, 0);
153             DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
154                        NULL, LicenceProc);
155             EnableWindow(hwnd, 1);
156             SetActiveWindow(hwnd);
157             return 0;
158         }
159         return 0;
160       case WM_CLOSE:
161         abtbox = NULL;
162         DestroyWindow (hwnd);
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          * Put the treeview selection on to the Session panel. This
1102          * should also cause creation of the relevant controls.
1103          */
1104         TreeView_SelectItem(treeview, hsession);
1105
1106         /*
1107          * Set focus into the first available control.
1108          */
1109         {
1110             HWND ctl;
1111             ctl = GetDlgItem(hwnd, IDC_HOST);
1112             if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1113             SetFocus(ctl);
1114         }
1115
1116         SetWindowLong(hwnd, GWL_USERDATA, 1);
1117         return 0;
1118       case WM_LBUTTONUP:
1119         /*
1120          * Button release should trigger WM_OK if there was a
1121          * previous double click on the session list.
1122          */
1123         ReleaseCapture();
1124         if (readytogo)
1125             SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1126         break;
1127       case WM_NOTIFY:
1128         if (LOWORD(wParam) == IDCX_TREEVIEW &&
1129             ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1130             HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1131             TVITEM item;
1132             int j;
1133             char buffer[64];
1134             item.hItem = i;
1135             item.pszText = buffer;
1136             item.cchTextMax = sizeof(buffer);
1137             item.mask = TVIF_TEXT;
1138             TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1139             for (j = controlstartvalue; j < controlendvalue; j++) {
1140                 HWND item = GetDlgItem(hwnd, j);
1141                 if (item)
1142                     DestroyWindow(item);
1143             }
1144             if (!strcmp(buffer, "Session"))
1145                 create_controls(hwnd, dlgtype, sessionpanelstart);
1146             if (!strcmp(buffer, "Keyboard"))
1147                 create_controls(hwnd, dlgtype, keyboardpanelstart);
1148             if (!strcmp(buffer, "Terminal"))
1149                 create_controls(hwnd, dlgtype, terminalpanelstart);
1150             if (!strcmp(buffer, "Window"))
1151                 create_controls(hwnd, dlgtype, windowpanelstart);
1152             if (!strcmp(buffer, "Appearance"))
1153                 create_controls(hwnd, dlgtype, appearancepanelstart);
1154             if (!strcmp(buffer, "Tunnels"))
1155                 create_controls(hwnd, dlgtype, tunnelspanelstart);
1156             if (!strcmp(buffer, "Connection"))
1157                 create_controls(hwnd, dlgtype, connectionpanelstart);
1158             if (!strcmp(buffer, "Telnet"))
1159                 create_controls(hwnd, dlgtype, telnetpanelstart);
1160             if (!strcmp(buffer, "Rlogin"))
1161                 create_controls(hwnd, dlgtype, rloginpanelstart);
1162             if (!strcmp(buffer, "SSH"))
1163                 create_controls(hwnd, dlgtype, sshpanelstart);
1164             if (!strcmp(buffer, "Selection"))
1165                 create_controls(hwnd, dlgtype, selectionpanelstart);
1166             if (!strcmp(buffer, "Colours"))
1167                 create_controls(hwnd, dlgtype, colourspanelstart);
1168             if (!strcmp(buffer, "Translation"))
1169                 create_controls(hwnd, dlgtype, translationpanelstart);
1170
1171             init_dlg_ctrls(hwnd);
1172
1173             SetFocus (((LPNMHDR)lParam)->hwndFrom);   /* ensure focus stays */
1174             return 0;
1175         }
1176         break;
1177       case WM_COMMAND:
1178         /*
1179          * Only process WM_COMMAND once the dialog is fully formed.
1180          */
1181         if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1182           case IDOK:
1183             if (*cfg.host)
1184                 EndDialog (hwnd, 1);
1185             else
1186                 MessageBeep (0);
1187             return 0;
1188           case IDCANCEL:
1189             EndDialog (hwnd, 0);
1190             return 0;
1191           case IDC_PROTTELNET:
1192           case IDC_PROTRLOGIN:
1193           case IDC_PROTSSH:
1194           case IDC_PROTRAW:
1195             if (HIWORD(wParam) == BN_CLICKED ||
1196                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1197                 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1198                 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1199                 int k = IsDlgButtonChecked (hwnd, IDC_PROTRLOGIN);
1200                 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN : PROT_RAW ;
1201                 if ((cfg.protocol == PROT_SSH && cfg.port != 22) ||
1202                     (cfg.protocol == PROT_TELNET && cfg.port != 23) ||
1203                     (cfg.protocol == PROT_RLOGIN && cfg.port != 513)) {
1204                     cfg.port = i ? 22 : j ? 23 : 513;
1205                     SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1206                 }
1207             }
1208             break;
1209           case IDC_HOST:
1210             if (HIWORD(wParam) == EN_CHANGE)
1211                 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1212                                 sizeof(cfg.host)-1);
1213             break;
1214           case IDC_PORT:
1215             if (HIWORD(wParam) == EN_CHANGE) {
1216                 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1217                 if (isdigit(portname[0]))
1218                     MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1219                 else {
1220                     service = getservbyname(portname, NULL);
1221                     if (service) cfg.port = ntohs(service->s_port);
1222                     else cfg.port = 0;
1223                 }
1224             }
1225             break;
1226           case IDC_SESSEDIT:
1227             if (HIWORD(wParam) == EN_CHANGE) {
1228                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1229                                     (WPARAM) -1, 0);
1230                 GetDlgItemText (hwnd, IDC_SESSEDIT,
1231                                 savedsession, sizeof(savedsession)-1);
1232                 savedsession[sizeof(savedsession)-1] = '\0';
1233             }
1234             break;
1235           case IDC_SESSSAVE:
1236             if (HIWORD(wParam) == BN_CLICKED ||
1237                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1238                 /*
1239                  * Save a session
1240                  */
1241                 char str[2048];
1242                 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1243                 if (!*str) {
1244                     int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1245                                                 LB_GETCURSEL, 0, 0);
1246                     if (n == LB_ERR) {
1247                         MessageBeep(0);
1248                         break;
1249                     }
1250                     strcpy (str, sessions[n]);
1251                 }
1252                 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1253                 get_sesslist (FALSE);
1254                 get_sesslist (TRUE);
1255                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1256                                     0, 0);
1257                 for (i = 0; i < nsessions; i++)
1258                     SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1259                                         0, (LPARAM) (sessions[i]));
1260                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1261                                     (WPARAM) -1, 0);
1262             }
1263             break;
1264           case IDC_SESSLIST:
1265           case IDC_SESSLOAD:
1266             if (LOWORD(wParam) == IDC_SESSLOAD &&
1267                 HIWORD(wParam) != BN_CLICKED &&
1268                 HIWORD(wParam) != BN_DOUBLECLICKED)
1269                 break;
1270             if (LOWORD(wParam) == IDC_SESSLIST &&
1271                 HIWORD(wParam) != LBN_DBLCLK)
1272                 break;
1273             {
1274                 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1275                                             LB_GETCURSEL, 0, 0);
1276                 int isdef;
1277                 if (n == LB_ERR) {
1278                     MessageBeep(0);
1279                     break;
1280                 }
1281                 isdef = !strcmp(sessions[n], "Default Settings");
1282                 load_settings (sessions[n], !isdef, &cfg);
1283                 init_dlg_ctrls(hwnd);
1284                 if (!isdef)
1285                     SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1286                 else
1287                     SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1288             }
1289             if (LOWORD(wParam) == IDC_SESSLIST) {
1290                 /*
1291                  * A double-click on a saved session should
1292                  * actually start the session, not just load it.
1293                  * Unless it's Default Settings or some other
1294                  * host-less set of saved settings.
1295                  */
1296                 if (*cfg.host) {
1297                     readytogo = TRUE;
1298                     SetCapture(hwnd);
1299                 }
1300             }
1301             break;
1302           case IDC_SESSDEL:
1303             if (HIWORD(wParam) == BN_CLICKED ||
1304                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1305                 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1306                                             LB_GETCURSEL, 0, 0);
1307                 if (n == LB_ERR || n == 0) {
1308                     MessageBeep(0);
1309                     break;
1310                 }
1311                 del_settings(sessions[n]);
1312                 get_sesslist (FALSE);
1313                 get_sesslist (TRUE);
1314                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1315                                     0, 0);
1316                 for (i = 0; i < nsessions; i++)
1317                     SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1318                                         0, (LPARAM) (sessions[i]));
1319                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1320                                     (WPARAM) -1, 0);
1321             }
1322           case IDC_PINGEDIT:
1323             if (HIWORD(wParam) == EN_CHANGE)
1324                 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1325             break;
1326           case IDC_DEL008:
1327           case IDC_DEL127:
1328             if (HIWORD(wParam) == BN_CLICKED ||
1329                 HIWORD(wParam) == BN_DOUBLECLICKED)
1330                 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1331             break;
1332           case IDC_HOMETILDE:
1333           case IDC_HOMERXVT:
1334             if (HIWORD(wParam) == BN_CLICKED ||
1335                 HIWORD(wParam) == BN_DOUBLECLICKED)
1336                 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1337             break;
1338           case IDC_FUNCXTERM:
1339             if (HIWORD(wParam) == BN_CLICKED ||
1340                 HIWORD(wParam) == BN_DOUBLECLICKED)
1341                 cfg.funky_type = 2;
1342             break;
1343           case IDC_FUNCVT400:
1344             if (HIWORD(wParam) == BN_CLICKED ||
1345                 HIWORD(wParam) == BN_DOUBLECLICKED)
1346                 cfg.funky_type = 3;
1347             break;
1348           case IDC_FUNCTILDE:
1349           case IDC_FUNCLINUX:
1350             if (HIWORD(wParam) == BN_CLICKED ||
1351                 HIWORD(wParam) == BN_DOUBLECLICKED)
1352                 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1353             break;
1354           case IDC_KPNORMAL:
1355           case IDC_KPAPPLIC:
1356             if (HIWORD(wParam) == BN_CLICKED ||
1357                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1358                 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1359                 cfg.nethack_keypad = FALSE;
1360             }
1361             break;
1362           case IDC_KPNH:
1363             if (HIWORD(wParam) == BN_CLICKED ||
1364                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1365                 cfg.app_keypad = FALSE;
1366                 cfg.nethack_keypad = TRUE;
1367             }
1368             break;
1369           case IDC_CURNORMAL:
1370           case IDC_CURAPPLIC:
1371             if (HIWORD(wParam) == BN_CLICKED ||
1372                 HIWORD(wParam) == BN_DOUBLECLICKED)
1373                 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1374             break;
1375           case IDC_NOAPPLICC:
1376             if (HIWORD(wParam) == BN_CLICKED ||
1377                 HIWORD(wParam) == BN_DOUBLECLICKED)
1378                 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1379             break;
1380           case IDC_NOAPPLICK:
1381             if (HIWORD(wParam) == BN_CLICKED ||
1382                 HIWORD(wParam) == BN_DOUBLECLICKED)
1383                 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1384             break;
1385           case IDC_ALTF4:
1386             if (HIWORD(wParam) == BN_CLICKED ||
1387                 HIWORD(wParam) == BN_DOUBLECLICKED)
1388                 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1389             break;
1390           case IDC_ALTSPACE:
1391             if (HIWORD(wParam) == BN_CLICKED ||
1392                 HIWORD(wParam) == BN_DOUBLECLICKED)
1393                 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1394             break;
1395           case IDC_ALTONLY:
1396             if (HIWORD(wParam) == BN_CLICKED ||
1397                 HIWORD(wParam) == BN_DOUBLECLICKED)
1398                 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1399             break;
1400           case IDC_LDISCTERM:
1401             if (HIWORD(wParam) == BN_CLICKED ||
1402                 HIWORD(wParam) == BN_DOUBLECLICKED)
1403                 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1404             break;
1405           case IDC_ALWAYSONTOP:
1406             if (HIWORD(wParam) == BN_CLICKED ||
1407                 HIWORD(wParam) == BN_DOUBLECLICKED)
1408                 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1409             break;
1410           case IDC_SCROLLKEY:
1411             if (HIWORD(wParam) == BN_CLICKED ||
1412                 HIWORD(wParam) == BN_DOUBLECLICKED)
1413                 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1414             break;
1415           case IDC_SCROLLDISP:
1416             if (HIWORD(wParam) == BN_CLICKED ||
1417                 HIWORD(wParam) == BN_DOUBLECLICKED)
1418                 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1419             break;
1420           case IDC_COMPOSEKEY:
1421             if (HIWORD(wParam) == BN_CLICKED ||
1422                 HIWORD(wParam) == BN_DOUBLECLICKED)
1423                 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1424             break;
1425           case IDC_WRAPMODE:
1426             if (HIWORD(wParam) == BN_CLICKED ||
1427                 HIWORD(wParam) == BN_DOUBLECLICKED)
1428                 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1429             break;
1430           case IDC_DECOM:
1431             if (HIWORD(wParam) == BN_CLICKED ||
1432                 HIWORD(wParam) == BN_DOUBLECLICKED)
1433                 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1434             break;
1435           case IDC_LFHASCR:
1436             if (HIWORD(wParam) == BN_CLICKED ||
1437                 HIWORD(wParam) == BN_DOUBLECLICKED)
1438                 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1439             break;
1440           case IDC_ROWSEDIT:
1441             if (HIWORD(wParam) == EN_CHANGE)
1442                 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1443             break;
1444           case IDC_COLSEDIT:
1445             if (HIWORD(wParam) == EN_CHANGE)
1446                 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1447             break;
1448           case IDC_SAVEEDIT:
1449             if (HIWORD(wParam) == EN_CHANGE)
1450                 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1451             break;
1452           case IDC_CHOOSEFONT:
1453             lf.lfHeight = cfg.fontheight;
1454             lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1455             lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1456             lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1457             lf.lfCharSet = cfg.fontcharset;
1458             lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1459             lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1460             lf.lfQuality = DEFAULT_QUALITY;
1461             lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1462             strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1463             lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1464
1465             cf.lStructSize = sizeof(cf);
1466             cf.hwndOwner = hwnd;
1467             cf.lpLogFont = &lf;
1468             cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1469                 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1470
1471             if (ChooseFont (&cf)) {
1472                 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1473                 cfg.font[sizeof(cfg.font)-1] = '\0';
1474                 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1475                 cfg.fontcharset = lf.lfCharSet;
1476                 cfg.fontheight = lf.lfHeight;
1477                 fmtfont (fontstatic);
1478                 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1479             }
1480             break;
1481           case IDC_BEEP:
1482             if (HIWORD(wParam) == BN_CLICKED ||
1483                 HIWORD(wParam) == BN_DOUBLECLICKED)
1484                 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1485             break;
1486           case IDC_BLINKTEXT:
1487             if (HIWORD(wParam) == BN_CLICKED ||
1488                 HIWORD(wParam) == BN_DOUBLECLICKED)
1489                 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1490             break;
1491           case IDC_BCE:
1492             if (HIWORD(wParam) == BN_CLICKED ||
1493                 HIWORD(wParam) == BN_DOUBLECLICKED)
1494                 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1495             break;
1496           case IDC_WINNAME:
1497             if (HIWORD(wParam) == BN_CLICKED ||
1498                 HIWORD(wParam) == BN_DOUBLECLICKED)
1499                 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1500             break;
1501           case IDC_HIDEMOUSE:
1502             if (HIWORD(wParam) == BN_CLICKED ||
1503                 HIWORD(wParam) == BN_DOUBLECLICKED)
1504                 cfg.hide_mouseptr = IsDlgButtonChecked (hwnd, IDC_HIDEMOUSE);
1505             break;
1506           case IDC_CURBLOCK:
1507             if (HIWORD(wParam) == BN_CLICKED ||
1508                 HIWORD(wParam) == BN_DOUBLECLICKED)
1509                 cfg.cursor_type = 0;
1510             break;
1511           case IDC_CURUNDER:
1512             if (HIWORD(wParam) == BN_CLICKED ||
1513                 HIWORD(wParam) == BN_DOUBLECLICKED)
1514                 cfg.cursor_type = 1;
1515             break;
1516           case IDC_CURVERT:
1517             if (HIWORD(wParam) == BN_CLICKED ||
1518                 HIWORD(wParam) == BN_DOUBLECLICKED)
1519                 cfg.cursor_type = 2;
1520             break;
1521           case IDC_BLINKCUR:
1522             if (HIWORD(wParam) == BN_CLICKED ||
1523                 HIWORD(wParam) == BN_DOUBLECLICKED)
1524                 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1525             break;
1526           case IDC_SCROLLBAR:
1527             if (HIWORD(wParam) == BN_CLICKED ||
1528                 HIWORD(wParam) == BN_DOUBLECLICKED)
1529                 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1530             break;
1531           case IDC_LOCKSIZE:
1532              if (HIWORD(wParam) == BN_CLICKED ||
1533                  HIWORD(wParam) == BN_DOUBLECLICKED)
1534                 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1535             break;
1536           case IDC_WINEDIT:
1537             if (HIWORD(wParam) == EN_CHANGE)
1538                 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1539                                 sizeof(cfg.wintitle)-1);
1540             break;
1541           case IDC_CLOSEEXIT:
1542             if (HIWORD(wParam) == BN_CLICKED ||
1543                 HIWORD(wParam) == BN_DOUBLECLICKED)
1544                 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1545             break;
1546           case IDC_CLOSEWARN:
1547             if (HIWORD(wParam) == BN_CLICKED ||
1548                 HIWORD(wParam) == BN_DOUBLECLICKED)
1549                 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1550             break;
1551           case IDC_TTEDIT:
1552             if (HIWORD(wParam) == EN_CHANGE)
1553             GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1554                             sizeof(cfg.termtype)-1);
1555             break;
1556           case IDC_LGFEDIT:
1557             if (HIWORD(wParam) == EN_CHANGE)
1558             GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1559                             sizeof(cfg.logfilename)-1);
1560             break;
1561           case IDC_LGFBUTTON:
1562             memset(&of, 0, sizeof(of));
1563 #ifdef OPENFILENAME_SIZE_VERSION_400
1564             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1565 #else
1566             of.lStructSize = sizeof(of);
1567 #endif
1568             of.hwndOwner = hwnd;
1569             of.lpstrFilter = "All Files\0*\0\0\0";
1570             of.lpstrCustomFilter = NULL;
1571             of.nFilterIndex = 1;
1572             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1573             of.nMaxFile = sizeof(filename);
1574             of.lpstrFileTitle = NULL;
1575             of.lpstrInitialDir = NULL;
1576             of.lpstrTitle = "Select session log file";
1577             of.Flags = 0;
1578             if (GetSaveFileName(&of)) {
1579                 strcpy(cfg.keyfile, filename);
1580                 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
1581             }
1582             break;
1583           case IDC_LSTATOFF:
1584           case IDC_LSTATASCII:
1585           case IDC_LSTATRAW:
1586             if (HIWORD(wParam) == BN_CLICKED ||
1587                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1588                 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1589                 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1590                 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1591             }
1592             break;
1593           case IDC_TSEDIT:
1594           case IDC_R_TSEDIT:
1595             if (HIWORD(wParam) == EN_CHANGE)
1596                 GetDlgItemText (hwnd, LOWORD(wParam), cfg.termspeed,
1597                                 sizeof(cfg.termspeed)-1);
1598             break;
1599           case IDC_LOGEDIT:
1600             if (HIWORD(wParam) == EN_CHANGE)
1601                 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1602                                 sizeof(cfg.username)-1);
1603             break;
1604           case IDC_RLLUSEREDIT:
1605             if (HIWORD(wParam) == EN_CHANGE)
1606                 GetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername,
1607                                 sizeof(cfg.localusername)-1);
1608             break;
1609           case IDC_EMBSD:
1610           case IDC_EMRFC:
1611             cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1612             break;
1613           case IDC_ENVADD:
1614             if (HIWORD(wParam) == BN_CLICKED ||
1615                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1616               char str[sizeof(cfg.environmt)];
1617                 char *p;
1618                 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1619                 if (!*str) {
1620                     MessageBeep(0);
1621                     break;
1622                 }
1623                 p = str + strlen(str);
1624                 *p++ = '\t';
1625                 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1626                 if (!*p) {
1627                     MessageBeep(0);
1628                     break;
1629                 }
1630               p = cfg.environmt;
1631                 while (*p) {
1632                     while (*p) p++;
1633                     p++;
1634                 }
1635               if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1636                     strcpy (p, str);
1637                     p[strlen(str)+1] = '\0';
1638                     SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1639                                         0, (LPARAM)str);
1640                     SetDlgItemText (hwnd, IDC_VAREDIT, "");
1641                     SetDlgItemText (hwnd, IDC_VALEDIT, "");
1642                 } else {
1643                     MessageBox(hwnd, "Environment too big", "PuTTY Error",
1644                                MB_OK | MB_ICONERROR);
1645                 }
1646             }
1647             break;
1648           case IDC_ENVREMOVE:
1649             if (HIWORD(wParam) != BN_CLICKED &&
1650                 HIWORD(wParam) != BN_DOUBLECLICKED)
1651                 break;
1652             i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1653             if (i == LB_ERR)
1654                 MessageBeep (0);
1655             else {
1656                 char *p, *q;
1657
1658                 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1659                                     i, 0);
1660               p = cfg.environmt;
1661                 while (i > 0) {
1662                     if (!*p)
1663                         goto disaster;
1664                     while (*p) p++;
1665                     p++;
1666                     i--;
1667                 }
1668                 q = p;
1669                 if (!*p)
1670                     goto disaster;
1671                 while (*p) p++;
1672                 p++;
1673                 while (*p) {
1674                     while (*p)
1675                         *q++ = *p++;
1676                     *q++ = *p++;
1677                 }
1678                 *q = '\0';
1679                 disaster:;
1680             }
1681             break;
1682           case IDC_NOPTY:
1683             if (HIWORD(wParam) == BN_CLICKED ||
1684                 HIWORD(wParam) == BN_DOUBLECLICKED)
1685                 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1686             break;
1687           case IDC_COMPRESS:
1688             if (HIWORD(wParam) == BN_CLICKED ||
1689                 HIWORD(wParam) == BN_DOUBLECLICKED)
1690                 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1691             break;
1692           case IDC_BUGGYMAC:
1693             if (HIWORD(wParam) == BN_CLICKED ||
1694                 HIWORD(wParam) == BN_DOUBLECLICKED)
1695                 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1696             break;
1697           case IDC_AGENTFWD:
1698             if (HIWORD(wParam) == BN_CLICKED ||
1699                 HIWORD(wParam) == BN_DOUBLECLICKED)
1700                 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1701             break;
1702           case IDC_CIPHER3DES:
1703           case IDC_CIPHERBLOWF:
1704           case IDC_CIPHERDES:
1705             if (HIWORD(wParam) == BN_CLICKED ||
1706                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1707                 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1708                     cfg.cipher = CIPHER_3DES;
1709                 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1710                     cfg.cipher = CIPHER_BLOWFISH;
1711                 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1712                     cfg.cipher = CIPHER_DES;
1713             }
1714             break;
1715           case IDC_SSHPROT1:
1716           case IDC_SSHPROT2:
1717             if (HIWORD(wParam) == BN_CLICKED ||
1718                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1719                 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1720                     cfg.sshprot = 1;
1721                 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1722                     cfg.sshprot = 2;
1723             }
1724             break;
1725           case IDC_AUTHTIS:
1726             if (HIWORD(wParam) == BN_CLICKED ||
1727                 HIWORD(wParam) == BN_DOUBLECLICKED)
1728                 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1729             break;
1730           case IDC_PKEDIT:
1731             if (HIWORD(wParam) == EN_CHANGE)
1732                 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1733                                 sizeof(cfg.keyfile)-1);
1734             break;
1735           case IDC_CMDEDIT:
1736             if (HIWORD(wParam) == EN_CHANGE)
1737                 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1738                                 sizeof(cfg.remote_cmd)-1);
1739             break;
1740           case IDC_PKBUTTON:
1741             memset(&of, 0, sizeof(of));
1742 #ifdef OPENFILENAME_SIZE_VERSION_400
1743             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1744 #else
1745             of.lStructSize = sizeof(of);
1746 #endif
1747             of.hwndOwner = hwnd;
1748             of.lpstrFilter = "All Files\0*\0\0\0";
1749             of.lpstrCustomFilter = NULL;
1750             of.nFilterIndex = 1;
1751             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1752             of.nMaxFile = sizeof(filename);
1753             of.lpstrFileTitle = NULL;
1754             of.lpstrInitialDir = NULL;
1755             of.lpstrTitle = "Select Public Key File";
1756             of.Flags = 0;
1757             if (GetOpenFileName(&of)) {
1758                 strcpy(cfg.keyfile, filename);
1759                 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1760             }
1761             break;
1762           case IDC_MBWINDOWS:
1763           case IDC_MBXTERM:
1764             cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1765             break;
1766           case IDC_CCSET:
1767             {
1768                 BOOL ok;
1769                 int i;
1770                 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1771
1772                 if (!ok)
1773                     MessageBeep (0);
1774                 else {
1775                     for (i=0; i<256; i++)
1776                         if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1777                                                 i, 0)) {
1778                             char str[100];
1779                             cfg.wordness[i] = n;
1780                             SendDlgItemMessage (hwnd, IDC_CCLIST,
1781                                                 LB_DELETESTRING, i, 0);
1782                             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1783                                     (i>=0x21 && i != 0x7F) ? i : ' ',
1784                                     cfg.wordness[i]);
1785                             SendDlgItemMessage (hwnd, IDC_CCLIST,
1786                                                 LB_INSERTSTRING, i,
1787                                                 (LPARAM)str);
1788                         }
1789                 }
1790             }
1791             break;
1792           case IDC_BOLDCOLOUR:
1793             if (HIWORD(wParam) == BN_CLICKED ||
1794                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1795                 int n, i;
1796                 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1797                 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1798                 if (n != 12+10*cfg.bold_colour) {
1799                     for (i=n; i-- >0 ;)
1800                         SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1801                                                 LB_DELETESTRING, i, 0);
1802                     for (i=0; i<22; i++)
1803                         if (cfg.bold_colour || permcolour[i])
1804                             SendDlgItemMessage (hwnd, IDC_COLOURLIST, 
1805                                                 LB_ADDSTRING, 0,
1806                                                 (LPARAM) colours[i]);
1807                 }
1808             }
1809             break;
1810           case IDC_PALETTE:
1811             if (HIWORD(wParam) == BN_CLICKED ||
1812                 HIWORD(wParam) == BN_DOUBLECLICKED)
1813                 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1814             break;
1815           case IDC_COLOURLIST:
1816             if (HIWORD(wParam) == LBN_DBLCLK ||
1817                 HIWORD(wParam) == LBN_SELCHANGE) {
1818                 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1819                                             0, 0);
1820                 if (!cfg.bold_colour)
1821                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1822                 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1823                 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1824                 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1825             }
1826             break;
1827           case IDC_CHANGE:
1828             if (HIWORD(wParam) == BN_CLICKED ||
1829                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1830                 static CHOOSECOLOR cc;
1831                 static DWORD custom[16] = {0};   /* zero initialisers */
1832                 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1833                                             0, 0);
1834                 if (!cfg.bold_colour)
1835                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1836                 cc.lStructSize = sizeof(cc);
1837                 cc.hwndOwner = hwnd;
1838                 cc.hInstance = (HWND)hinst;
1839                 cc.lpCustColors = custom;
1840                 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1841                                     cfg.colours[i][2]);
1842                 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1843                 if (ChooseColor(&cc)) {
1844                     cfg.colours[i][0] =
1845                         (unsigned char) (cc.rgbResult & 0xFF);
1846                     cfg.colours[i][1] =
1847                         (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1848                     cfg.colours[i][2] =
1849                         (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1850                     SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1851                                    FALSE);
1852                     SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1853                                    FALSE);
1854                     SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1855                                    FALSE);
1856                 }
1857             }
1858             break;
1859           case IDC_NOXLAT:
1860           case IDC_KOI8WIN1251:
1861           case IDC_88592WIN1250:
1862           case IDC_88592CP852:
1863             cfg.xlat_enablekoiwin =
1864                 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1865             cfg.xlat_88592w1250 =
1866                 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1867             cfg.xlat_88592cp852 =
1868                 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1869             break;
1870           case IDC_CAPSLOCKCYR:
1871             if (HIWORD(wParam) == BN_CLICKED ||
1872                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1873                 cfg.xlat_capslockcyr =
1874                     IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1875             }
1876             break;
1877           case IDC_VTXWINDOWS:
1878           case IDC_VTOEMANSI:
1879           case IDC_VTOEMONLY:
1880           case IDC_VTPOORMAN:
1881             cfg.vtmode =
1882                 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1883                  IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1884                  IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1885                  VT_POORMAN);
1886             break;
1887           case IDC_X11_FORWARD:
1888             if (HIWORD(wParam) == BN_CLICKED ||
1889                 HIWORD(wParam) == BN_DOUBLECLICKED)
1890                 cfg.x11_forward = IsDlgButtonChecked (hwnd, IDC_X11_FORWARD);
1891             break;
1892           case IDC_X11_DISPLAY:
1893             if (HIWORD(wParam) == EN_CHANGE)
1894                 GetDlgItemText (hwnd, IDC_X11_DISPLAY, cfg.x11_display,
1895                                 sizeof(cfg.x11_display)-1);
1896             break;
1897         }
1898         return 0;
1899       case WM_CLOSE:
1900         EndDialog (hwnd, 0);
1901         return 0;
1902
1903         /* Grrr Explorer will maximize Dialogs! */
1904       case WM_SIZE:
1905         if (wParam == SIZE_MAXIMIZED)
1906            force_normal(hwnd);
1907         return 0;
1908     }
1909     return 0;
1910 }
1911
1912 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1913                                  WPARAM wParam, LPARAM lParam) {
1914     static HWND page = NULL;
1915
1916     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1917     }
1918     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1919         EnableWindow(hwnd, 0);
1920         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1921                   GetParent(hwnd), AboutProc);
1922         EnableWindow(hwnd, 1);
1923         SetActiveWindow(hwnd);
1924     }
1925     return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1926 }
1927
1928 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1929                                    WPARAM wParam, LPARAM lParam) {
1930     static HWND page;
1931     return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1932 }
1933
1934 void defuse_showwindow(void) {
1935     /*
1936      * Work around the fact that the app's first call to ShowWindow
1937      * will ignore the default in favour of the shell-provided
1938      * setting.
1939      */
1940     {
1941         HWND hwnd;
1942         hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1943                              NULL, NullDlgProc);
1944         ShowWindow(hwnd, SW_HIDE);
1945         DestroyWindow(hwnd);
1946     }
1947 }
1948
1949 int do_config (void) {
1950     int ret;
1951
1952     get_sesslist(TRUE);
1953     savedsession[0] = '\0';
1954     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1955     get_sesslist(FALSE);
1956
1957     return ret;
1958 }
1959
1960 int do_reconfig (HWND hwnd) {
1961     Config backup_cfg;
1962     int ret;
1963
1964     backup_cfg = cfg;                  /* structure copy */
1965     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1966     if (!ret)
1967         cfg = backup_cfg;              /* structure copy */
1968
1969     return ret;
1970 }
1971
1972 void logevent (char *string) {
1973     if (nevents >= negsize) {
1974         negsize += 64;
1975         events = srealloc (events, negsize * sizeof(*events));
1976     }
1977     events[nevents] = smalloc(1+strlen(string));
1978     strcpy (events[nevents], string);
1979     nevents++;
1980     if (logbox) {
1981         int count;
1982         SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1983                             0, (LPARAM)string);
1984         count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1985         SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1986     }
1987 }
1988
1989 void showeventlog (HWND hwnd) {
1990     if (!logbox) {
1991         logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1992                                hwnd, LogProc);
1993         ShowWindow (logbox, SW_SHOWNORMAL);
1994     }
1995 }
1996
1997 void showabout (HWND hwnd) {
1998     if (!abtbox) {
1999         abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2000                                hwnd, AboutProc);
2001         ShowWindow (abtbox, SW_SHOWNORMAL);
2002     }
2003 }
2004
2005 void verify_ssh_host_key(char *host, int port, char *keytype,
2006                          char *keystr, char *fingerprint) {
2007     int ret;
2008
2009     static const char absentmsg[] =
2010         "The server's host key is not cached in the registry. You\n"
2011         "have no guarantee that the server is the computer you\n"
2012         "think it is.\n"
2013         "The server's key fingerprint is:\n"
2014         "%s\n"
2015         "If you trust this host, hit Yes to add the key to\n"
2016         "PuTTY's cache and carry on connecting.\n"
2017         "If you do not trust this host, hit No to abandon the\n"
2018         "connection.\n";
2019
2020     static const char wrongmsg[] =
2021         "WARNING - POTENTIAL SECURITY BREACH!\n"
2022         "\n"
2023         "The server's host key does not match the one PuTTY has\n"
2024         "cached in the registry. This means that either the\n"
2025         "server administrator has changed the host key, or you\n"
2026         "have actually connected to another computer pretending\n"
2027         "to be the server.\n"
2028         "The new key fingerprint is:\n"
2029         "%s\n"
2030         "If you were expecting this change and trust the new key,\n"
2031         "hit Yes to update PuTTY's cache and continue connecting.\n"
2032         "If you want to carry on connecting but without updating\n"
2033         "the cache, hit No.\n"
2034         "If you want to abandon the connection completely, hit\n"
2035         "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2036         "choice.\n";
2037
2038     static const char mbtitle[] = "PuTTY Security Alert";
2039
2040     
2041     char message[160+                  /* sensible fingerprint max size */
2042                  (sizeof(absentmsg) > sizeof(wrongmsg) ?
2043                   sizeof(absentmsg) : sizeof(wrongmsg))];
2044
2045     /*
2046      * Verify the key against the registry.
2047      */
2048     ret = verify_host_key(host, port, keytype, keystr);
2049
2050     if (ret == 0)                      /* success - key matched OK */
2051         return;
2052     if (ret == 2) {                    /* key was different */
2053         int mbret;
2054         sprintf(message, wrongmsg, fingerprint);
2055         mbret = MessageBox(NULL, message, mbtitle,
2056                            MB_ICONWARNING | MB_YESNOCANCEL);
2057         if (mbret == IDYES)
2058             store_host_key(host, port, keytype, keystr);
2059         if (mbret == IDCANCEL)
2060             exit(0);
2061     }
2062     if (ret == 1) {                    /* key was absent */
2063         int mbret;
2064         sprintf(message, absentmsg, fingerprint);
2065         mbret = MessageBox(NULL, message, mbtitle,
2066                            MB_ICONWARNING | MB_YESNO);
2067         if (mbret == IDNO)
2068             exit(0);
2069         store_host_key(host, port, keytype, keystr);
2070     }
2071 }
2072
2073 /*
2074  * Ask whether to wipe a session log file before writing to it.
2075  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2076  */
2077 int askappend(char *filename) {
2078     static const char mbtitle[] = "PuTTY Log to File";
2079     static const char msgtemplate[] =
2080         "The session log file \"%.*s\" already exists.\n"
2081         "You can overwrite it with a new session log,\n"
2082         "append your session log to the end of it,\n"
2083         "or disable session logging for this session.\n"
2084         "Hit Yes to wipe the file, No to append to it,\n"
2085         "or Cancel to disable logging.";
2086     char message[sizeof(msgtemplate) + FILENAME_MAX];
2087     int mbret;
2088     sprintf(message, msgtemplate, FILENAME_MAX, filename);
2089
2090     mbret = MessageBox(NULL, message, mbtitle,
2091                         MB_ICONQUESTION | MB_YESNOCANCEL);
2092     if (mbret == IDYES)
2093         return 2;
2094     else if (mbret == IDNO)
2095         return 1;
2096     else
2097         return 0;
2098 }