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