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