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