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