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