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