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