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