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