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