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