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