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