]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
7f2c8a152bbfc87d5cd18741e29a04fc558e048d
[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
7 #include "ssh.h"
8 #include "putty.h"
9 #include "winstuff.h"
10 #include "win_res.h"
11 #include "storage.h"
12
13 static char **events = NULL;
14 static int nevents = 0, negsize = 0;
15
16 static HWND logbox = NULL, abtbox = NULL;
17
18 static int readytogo;
19
20 void force_normal(HWND hwnd)
21 {
22     static int recurse = 0;
23
24     WINDOWPLACEMENT wp;
25
26     if(recurse) return;
27     recurse = 1;
28
29     wp.length = sizeof(wp);
30     if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED)
31     {
32         wp.showCmd = SW_SHOWNORMAL;
33         SetWindowPlacement(hwnd, &wp);
34     }
35     recurse = 0;
36 }
37
38 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
39     BOOL ok;
40     int n;
41     n = GetDlgItemInt (hwnd, id, &ok, FALSE);
42     if (ok)
43         *result = n;
44 }
45
46 static int CALLBACK LogProc (HWND hwnd, UINT msg,
47                              WPARAM wParam, LPARAM lParam) {
48     int i;
49
50     switch (msg) {
51       case WM_INITDIALOG:
52         for (i=0; i<nevents; i++)
53             SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
54                                 0, (LPARAM)events[i]);
55         return 1;
56       case WM_COMMAND:
57         switch (LOWORD(wParam)) {
58           case IDOK:
59             logbox = NULL;
60             DestroyWindow (hwnd);
61             return 0;
62           case IDN_COPY:
63             if (HIWORD(wParam) == BN_CLICKED ||
64                 HIWORD(wParam) == BN_DOUBLECLICKED) {
65                 int selcount;
66                 int *selitems;
67                 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
68                                               LB_GETSELCOUNT, 0, 0);
69                 selitems = smalloc(selcount * sizeof(int));
70                 if (selitems) {
71                     int count = SendDlgItemMessage(hwnd, IDN_LIST,
72                                                    LB_GETSELITEMS,
73                                                    selcount, (LPARAM)selitems);
74                     int i;
75                     int size;
76                     char *clipdata;
77                     static unsigned char sel_nl[] = SEL_NL;
78
79                     if (count == 0) {  /* can't copy zero stuff */
80                         MessageBeep(0);
81                         break;
82                     }
83
84                     size = 0;
85                     for (i = 0; i < count; i++)
86                         size += strlen(events[selitems[i]]) + sizeof(sel_nl);
87
88                     clipdata = smalloc(size);
89                     if (clipdata) {
90                         char *p = clipdata;
91                         for (i = 0; i < count; i++) {
92                             char *q = events[selitems[i]];
93                             int qlen = strlen(q);
94                             memcpy(p, q, qlen);
95                             p += qlen;
96                             memcpy(p, sel_nl, sizeof(sel_nl));
97                             p += sizeof(sel_nl);
98                         }
99                         write_clip(clipdata, size, TRUE);
100                         sfree(clipdata);
101                     }
102                     sfree(selitems);
103
104                     for (i = 0; i < nevents; i++)
105                         SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
106                                            FALSE, i);
107                 }
108             }
109             return 0;
110         }
111         return 0;
112       case WM_CLOSE:
113         logbox = NULL;
114         DestroyWindow (hwnd);
115         return 0;
116     }
117     return 0;
118 }
119
120 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
121                                  WPARAM wParam, LPARAM lParam) {
122     switch (msg) {
123       case WM_INITDIALOG:
124         return 1;
125       case WM_COMMAND:
126         switch (LOWORD(wParam)) {
127           case IDOK:
128             EndDialog(hwnd, 1);
129             return 0;
130         }
131         return 0;
132       case WM_CLOSE:
133         EndDialog(hwnd, 1);
134         return 0;
135     }
136     return 0;
137 }
138
139 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
140                                WPARAM wParam, LPARAM lParam) {
141     switch (msg) {
142       case WM_INITDIALOG:
143         SetDlgItemText (hwnd, IDA_VERSION, ver);
144         return 1;
145       case WM_COMMAND:
146         switch (LOWORD(wParam)) {
147           case IDOK:
148             abtbox = NULL;
149             DestroyWindow (hwnd);
150             return 0;
151           case IDA_LICENCE:
152             EnableWindow(hwnd, 0);
153             DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
154                        NULL, LicenceProc);
155             EnableWindow(hwnd, 1);
156             SetActiveWindow(hwnd);
157             return 0;
158         }
159         return 0;
160       case WM_CLOSE:
161         abtbox = NULL;
162         DestroyWindow (hwnd);
163         return 0;
164     }
165     return 0;
166 }
167
168 /*
169  * Null dialog procedure.
170  */
171 static int CALLBACK NullDlgProc (HWND hwnd, UINT msg,
172                                  WPARAM wParam, LPARAM lParam) {
173     return 0;
174 }
175
176 static char savedsession[2048];
177
178 enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
179
180     sessionpanelstart,
181     IDC_TITLE_SESSION,
182     IDC_BOX_SESSION1, IDC_BOXT_SESSION1,
183     IDC_BOX_SESSION2, IDC_BOXT_SESSION2,
184     IDC_BOX_SESSION3,
185     IDC_HOSTSTATIC,
186     IDC_HOST,
187     IDC_PORTSTATIC,
188     IDC_PORT,
189     IDC_PROTSTATIC,
190     IDC_PROTRAW,
191     IDC_PROTTELNET,
192     IDC_PROTSSH,
193     IDC_SESSSTATIC,
194     IDC_SESSEDIT,
195     IDC_SESSLIST,
196     IDC_SESSLOAD,
197     IDC_SESSSAVE,
198     IDC_SESSDEL,
199     IDC_CLOSEEXIT,
200     sessionpanelend,
201
202     keyboardpanelstart,
203     IDC_TITLE_KEYBOARD,
204     IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1,
205     IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2,
206     IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3,
207     IDC_DELSTATIC,
208     IDC_DEL008,
209     IDC_DEL127,
210     IDC_HOMESTATIC,
211     IDC_HOMETILDE,
212     IDC_HOMERXVT,
213     IDC_FUNCSTATIC,
214     IDC_FUNCTILDE,
215     IDC_FUNCLINUX,
216     IDC_FUNCXTERM,
217     IDC_FUNCVT400,
218     IDC_KPSTATIC,
219     IDC_KPNORMAL,
220     IDC_KPAPPLIC,
221     IDC_KPNH,
222     IDC_NOAPPLICK,
223     IDC_NOAPPLICC,
224     IDC_CURSTATIC,
225     IDC_CURNORMAL,
226     IDC_CURAPPLIC,
227     IDC_COMPOSEKEY,
228     keyboardpanelend,
229
230     terminalpanelstart,
231     IDC_TITLE_TERMINAL,
232     IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
233     IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2,
234     IDC_WRAPMODE,
235     IDC_DECOM,
236     IDC_LFHASCR,
237     IDC_BEEP,
238     IDC_BCE,
239     IDC_BLINKTEXT,
240     IDC_LDISCTERM,
241     IDC_LSTATSTATIC,
242     IDC_LSTATOFF,
243     IDC_LSTATASCII,
244     IDC_LSTATRAW,
245     IDC_LGFSTATIC,
246     IDC_LGFEDIT,
247     IDC_LGFBUTTON,
248     terminalpanelend,
249
250     windowpanelstart,
251     IDC_TITLE_WINDOW,
252     IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1,
253     IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2,
254     IDC_BOX_WINDOW3,
255     IDC_ROWSSTATIC,
256     IDC_ROWSEDIT,
257     IDC_COLSSTATIC,
258     IDC_COLSEDIT,
259     IDC_LOCKSIZE,
260     IDC_SCROLLBAR,
261     IDC_CLOSEWARN,
262     IDC_SAVESTATIC,
263     IDC_SAVEEDIT,
264     IDC_ALTF4,
265     IDC_ALTSPACE,
266     IDC_ALTONLY,
267     IDC_SCROLLKEY,
268     IDC_SCROLLDISP,
269     IDC_ALWAYSONTOP,
270     windowpanelend,
271
272     appearancepanelstart,
273     IDC_TITLE_APPEARANCE,
274     IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1,
275     IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2,
276     IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3,
277     IDC_CURSTATIC,
278     IDC_CURBLOCK,
279     IDC_CURUNDER,
280     IDC_CURVERT,
281     IDC_BLINKCUR,
282     IDC_FONTSTATIC,
283     IDC_CHOOSEFONT,
284     IDC_WINTITLE,
285     IDC_WINEDIT,
286     IDC_WINNAME,
287     appearancepanelend,
288
289     connectionpanelstart,
290     IDC_TITLE_CONNECTION,
291     IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1,
292     IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2,
293     IDC_TTSTATIC,
294     IDC_TTEDIT,
295     IDC_LOGSTATIC,
296     IDC_LOGEDIT,
297     IDC_PINGSTATIC,
298     IDC_PINGEDIT,
299     connectionpanelend,
300
301     telnetpanelstart,
302     IDC_TITLE_TELNET,
303     IDC_BOX_TELNET1, IDC_BOXT_TELNET1,
304     IDC_BOX_TELNET2, IDC_BOXT_TELNET2,
305     IDC_TSSTATIC,
306     IDC_TSEDIT,
307     IDC_ENVSTATIC,
308     IDC_VARSTATIC,
309     IDC_VAREDIT,
310     IDC_VALSTATIC,
311     IDC_VALEDIT,
312     IDC_ENVLIST,
313     IDC_ENVADD,
314     IDC_ENVREMOVE,
315     IDC_EMSTATIC,
316     IDC_EMBSD,
317     IDC_EMRFC,
318     telnetpanelend,
319
320     sshpanelstart,
321     IDC_TITLE_SSH,
322     IDC_BOX_SSH1, IDC_BOXT_SSH1,
323     IDC_BOX_SSH2, IDC_BOXT_SSH2,
324     IDC_BOX_SSH3, IDC_BOXT_SSH3,
325     IDC_NOPTY,
326     IDC_CIPHERSTATIC,
327     IDC_CIPHER3DES,
328     IDC_CIPHERBLOWF,
329     IDC_CIPHERDES,
330     IDC_BUGGYMAC,
331     IDC_AUTHTIS,
332     IDC_PKSTATIC,
333     IDC_PKEDIT,
334     IDC_PKBUTTON,
335     IDC_SSHPROTSTATIC,
336     IDC_SSHPROT1,
337     IDC_SSHPROT2,
338     IDC_AGENTFWD,
339     IDC_CMDSTATIC,
340     IDC_CMDEDIT,
341     IDC_COMPRESS,
342     sshpanelend,
343
344     selectionpanelstart,
345     IDC_TITLE_SELECTION,
346     IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
347     IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
348     IDC_MBSTATIC,
349     IDC_MBWINDOWS,
350     IDC_MBXTERM,
351     IDC_CCSTATIC,
352     IDC_CCLIST,
353     IDC_CCSET,
354     IDC_CCSTATIC2,
355     IDC_CCEDIT,
356     selectionpanelend,
357
358     colourspanelstart,
359     IDC_TITLE_COLOURS,
360     IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
361     IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
362     IDC_BOLDCOLOUR,
363     IDC_PALETTE,
364     IDC_COLOURSTATIC,
365     IDC_COLOURLIST,
366     IDC_RSTATIC,
367     IDC_GSTATIC,
368     IDC_BSTATIC,
369     IDC_RVALUE,
370     IDC_GVALUE,
371     IDC_BVALUE,
372     IDC_CHANGE,
373     colourspanelend,
374
375     translationpanelstart,
376     IDC_TITLE_TRANSLATION,
377     IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
378     IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
379     IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
380     IDC_XLATSTATIC,
381     IDC_NOXLAT,
382     IDC_KOI8WIN1251,
383     IDC_88592WIN1250,
384     IDC_88592CP852,
385     IDC_CAPSLOCKCYR,
386     IDC_VTSTATIC,
387     IDC_VTXWINDOWS,
388     IDC_VTOEMANSI,
389     IDC_VTOEMONLY,
390     IDC_VTPOORMAN,
391     translationpanelend,
392
393     controlendvalue
394 };
395
396 static const char *const colours[] = {
397     "Default Foreground", "Default Bold Foreground",
398     "Default Background", "Default Bold Background",
399     "Cursor Text", "Cursor Colour",
400     "ANSI Black", "ANSI Black Bold",
401     "ANSI Red", "ANSI Red Bold",
402     "ANSI Green", "ANSI Green Bold",
403     "ANSI Yellow", "ANSI Yellow Bold",
404     "ANSI Blue", "ANSI Blue Bold",
405     "ANSI Magenta", "ANSI Magenta Bold",
406     "ANSI Cyan", "ANSI Cyan Bold",
407     "ANSI White", "ANSI White Bold"
408 };
409 static const int permcolour[] = {
410     TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
411     TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
412     TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
413 };
414
415 static void fmtfont (char *buf) {
416     sprintf (buf, "Font: %s, ", cfg.font);
417     if (cfg.fontisbold)
418         strcat(buf, "bold, ");
419     if (cfg.fontheight == 0)
420         strcat (buf, "default height");
421     else
422         sprintf (buf+strlen(buf), "%d-%s",
423                  (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
424                  (cfg.fontheight < 0 ? "pixel" : "point"));
425 }
426
427 static void init_dlg_ctrls(HWND hwnd) {
428     int i;
429     char fontstatic[256];
430
431     SetDlgItemText (hwnd, IDC_HOST, cfg.host);
432     SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
433     SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
434     CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
435                       cfg.protocol==PROT_SSH ? IDC_PROTSSH :
436                       cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
437     SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
438
439     CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
440                       cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
441     CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
442                       cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
443     CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
444                       cfg.funky_type == 0 ? IDC_FUNCTILDE :
445                       cfg.funky_type == 1 ? IDC_FUNCLINUX :
446                       cfg.funky_type == 2 ? IDC_FUNCXTERM :
447                       cfg.funky_type == 3 ? IDC_FUNCVT400 :
448                       IDC_FUNCTILDE );
449     CheckDlgButton (hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
450     CheckDlgButton (hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
451     CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
452                       cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
453     CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
454                       cfg.nethack_keypad ? IDC_KPNH :
455                       cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
456     CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
457     CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
458     CheckDlgButton (hwnd, IDC_ALTONLY, cfg.alt_only);
459     CheckDlgButton (hwnd, IDC_COMPOSEKEY, cfg.compose_key);
460     CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
461     CheckDlgButton (hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
462     CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
463     CheckDlgButton (hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
464
465     CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
466     CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
467     CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
468     SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
469     SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
470     SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
471     fmtfont (fontstatic);
472     SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
473     CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
474     CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
475     CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
476
477     SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
478     CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
479     CheckRadioButton (hwnd, IDC_CURBLOCK, IDC_CURVERT,
480                       cfg.cursor_type==0 ? IDC_CURBLOCK :
481                       cfg.cursor_type==1 ? IDC_CURUNDER : IDC_CURVERT);
482     CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
483     CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
484     CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
485     CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
486     CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
487
488     SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
489     SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
490     SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
491     SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
492     CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
493                      cfg.logtype == 0 ? IDC_LSTATOFF :
494                      cfg.logtype == 1 ? IDC_LSTATASCII :
495                      IDC_LSTATRAW);
496     {
497         char *p = cfg.environmt;
498         while (*p) {
499             SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
500                                 (LPARAM) p);
501             p += strlen(p)+1;
502         }
503     }
504     CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
505                       cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
506
507     SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
508     SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
509     CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
510     CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
511     CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
512     CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
513     CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
514                       cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
515                       cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
516                       IDC_CIPHER3DES);
517     CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
518                       cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
519     CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
520     SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
521     SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
522
523     CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
524                       cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
525     {
526         static int tabs[4] = {25, 61, 96, 128};
527         SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
528                             (LPARAM) tabs);
529     }
530     for (i=0; i<256; i++) {
531         char str[100];
532         sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
533                 (i>=0x21 && i != 0x7F) ? i : ' ',
534                 cfg.wordness[i]);
535         SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
536                             (LPARAM) str);
537     }
538
539     CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
540     CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
541     {
542         int i, n;
543         n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
544         for (i=n; i-- >0 ;)
545             SendDlgItemMessage (hwnd, IDC_COLOURLIST,
546                                     LB_DELETESTRING, i, 0);
547         for (i=0; i<22; i++)
548             if (cfg.bold_colour || permcolour[i])
549                 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
550                                     (LPARAM) colours[i]);
551     }
552     SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
553     SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
554     SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
555     SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
556
557     CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
558                       cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
559                       cfg.xlat_88592cp852 ? IDC_88592CP852 :
560                       cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
561                       IDC_NOXLAT);
562     CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
563     CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
564                       cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
565                       cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
566                       cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
567                       IDC_VTPOORMAN);
568 }
569
570 static void hide(HWND hwnd, int hide, int minid, int maxid) {
571     int i;
572     for (i = minid; i < maxid; i++) {
573         HWND ctl = GetDlgItem(hwnd, i);
574         if (ctl) {
575             ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
576         }
577     }
578 }
579
580 struct treeview_faff {
581     HWND treeview;
582     HTREEITEM lastat[4];
583 };
584
585 static HTREEITEM treeview_insert(struct treeview_faff *faff,
586                                  int level, char *text) {
587     TVINSERTSTRUCT ins;
588     int i;
589     HTREEITEM newitem;
590     ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
591     ins.hInsertAfter = faff->lastat[level];
592 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
593 #define INSITEM DUMMYUNIONNAME.item
594 #else
595 #define INSITEM item
596 #endif
597     ins.INSITEM.mask = TVIF_TEXT;
598     ins.INSITEM.pszText = text;
599     newitem = TreeView_InsertItem(faff->treeview, &ins);
600     if (level > 0)
601         TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
602     faff->lastat[level] = newitem;
603     for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
604     return newitem;
605 }
606
607 /*
608  * This _huge_ function is the configuration box.
609  */
610 static int GenericMainDlgProc (HWND hwnd, UINT msg,
611                                WPARAM wParam, LPARAM lParam,
612                                int dlgtype) {
613     HWND hw, treeview;
614     struct treeview_faff tvfaff;
615     HTREEITEM hsession;
616     OPENFILENAME of;
617     char filename[sizeof(cfg.keyfile)];
618     CHOOSEFONT cf;
619     LOGFONT lf;
620     char fontstatic[256];
621     char portname[32];
622     struct servent * service;
623     int i;
624
625     switch (msg) {
626       case WM_INITDIALOG:
627         readytogo = 0;
628         SetWindowLong(hwnd, GWL_USERDATA, 0);
629         /*
630          * Centre the window.
631          */
632         {                              /* centre the window */
633             RECT rs, rd;
634
635             hw = GetDesktopWindow();
636             if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
637                 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
638                             (rs.bottom + rs.top + rd.top - rd.bottom)/2,
639                             rd.right-rd.left, rd.bottom-rd.top, TRUE);
640         }
641
642         /*
643          * Create the tree view.
644          */
645         {
646             RECT r;
647             WPARAM font;
648             HWND tvstatic;
649
650             r.left = 3; r.right = r.left + 75;
651             r.top = 3; r.bottom = r.top + 10;
652             MapDialogRect(hwnd, &r);
653             tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
654                                       WS_CHILD | WS_VISIBLE,
655                                       r.left, r.top,
656                                       r.right-r.left, r.bottom-r.top,
657                                       hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
658             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
659             SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
660
661             r.left = 3; r.right = r.left + 75;
662             r.top = 13; r.bottom = r.top + 206;
663             MapDialogRect(hwnd, &r);
664             treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
665                                       WS_CHILD | WS_VISIBLE |
666                                       WS_TABSTOP | TVS_HASLINES |
667                                       TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
668                                       TVS_LINESATROOT | TVS_SHOWSELALWAYS,
669                                       r.left, r.top,
670                                       r.right-r.left, r.bottom-r.top,
671                                       hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
672             font = SendMessage(hwnd, WM_GETFONT, 0, 0);
673             SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
674             tvfaff.treeview = treeview;
675             memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
676         }
677
678         /*
679          * Create the various panelfuls of controls.
680          */
681
682         /* The Session panel. Accelerators used: [acgo] nprthelsdx */
683         {
684             struct ctlpos cp;
685             ctlposinit(&cp, hwnd, 80, 3, 13);
686             bartitle(&cp, "Basic options for your PuTTY session",
687                      IDC_TITLE_SESSION);
688             if (dlgtype == 0) {
689                 beginbox(&cp, "Specify your connection by host name",
690                          IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
691                 multiedit(&cp,
692                           "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
693                           "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
694                 if (backends[2].backend == NULL) {
695                     /* this is PuTTYtel, so only two protocols available */
696                     radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
697                               "&Raw", IDC_PROTRAW,
698                               "&Telnet", IDC_PROTTELNET, NULL);
699                 } else {
700                     radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
701                               "&Raw", IDC_PROTRAW,
702                               "&Telnet", IDC_PROTTELNET,
703 #ifdef FWHACK
704                               "SS&H/hack",
705 #else
706                               "SS&H",
707 #endif
708                               IDC_PROTSSH, NULL);
709                 }
710                 endbox(&cp);
711                 beginbox(&cp, "Load, save or delete a stored session",
712                          IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
713                 sesssaver(&cp, "Sav&ed Sessions",
714                           IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
715                           "&Load", IDC_SESSLOAD,
716                           "&Save", IDC_SESSSAVE,
717                           "&Delete", IDC_SESSDEL, NULL);
718                 endbox(&cp);
719             }
720             beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
721             checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
722             endbox(&cp);
723
724             hsession = treeview_insert(&tvfaff, 0, "Session");
725         }
726
727         /* The Terminal panel. Accelerators used: [acgo] &dflbenuw */
728         {
729             struct ctlpos cp;
730             ctlposinit(&cp, hwnd, 80, 3, 13);
731             bartitle(&cp, "Options controlling the terminal emulation",
732                      IDC_TITLE_TERMINAL);
733             beginbox(&cp, "Set various terminal options",
734                      IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
735             checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
736             checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
737             checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
738             checkbox(&cp, "&Beep enabled", IDC_BEEP);
739             checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
740             checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
741             checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
742             endbox(&cp);
743
744             beginbox(&cp, "Control session logging",
745                      IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
746             radiobig(&cp,
747                      "Session logging:", IDC_LSTATSTATIC,
748                      "Logging turned &off completely", IDC_LSTATOFF,
749                      "Log printable output only", IDC_LSTATASCII,
750                      "Log all session output", IDC_LSTATRAW, NULL);
751             editbutton(&cp, "Log &file name:",
752                        IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
753                        IDC_LGFBUTTON);
754             endbox(&cp);
755
756             treeview_insert(&tvfaff, 0, "Terminal");
757         }
758
759         /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmietu */
760         {
761             struct ctlpos cp;
762             ctlposinit(&cp, hwnd, 80, 3, 13);
763             bartitle(&cp, "Options controlling the effects of keys",
764                      IDC_TITLE_KEYBOARD);
765             beginbox(&cp, "Change the sequences sent by:",
766                      IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
767             radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
768                       "Control-&H", IDC_DEL008,
769                       "Control-&? (127)", IDC_DEL127, NULL);
770             radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
771                       "&Standard", IDC_HOMETILDE,
772                       "&rxvt", IDC_HOMERXVT, NULL);
773             radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
774                       "ESC[n&~", IDC_FUNCTILDE,
775                       "&Linux", IDC_FUNCLINUX,
776                       "&Xterm R6", IDC_FUNCXTERM,
777                       "&VT400", IDC_FUNCVT400, NULL);
778             endbox(&cp);
779             beginbox(&cp, "Application keypad settings:",
780                      IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
781             checkbox(&cp,
782                      "Application c&ursor keys totally disabled",
783                      IDC_NOAPPLICC);
784             radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
785                       "&Normal", IDC_CURNORMAL,
786                       "A&pplication", IDC_CURAPPLIC, NULL);
787             checkbox(&cp,
788                      "Application ke&ypad keys totally disabled",
789                      IDC_NOAPPLICK);
790             radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
791                       "Nor&mal", IDC_KPNORMAL,
792                       "Appl&ication", IDC_KPAPPLIC,
793                       "N&etHack", IDC_KPNH, NULL);
794             endbox(&cp);
795             beginbox(&cp, "Enable extra keyboard features:",
796                      IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3);
797             checkbox(&cp, "Application and AltGr ac&t as Compose key",
798                      IDC_COMPOSEKEY);
799             endbox(&cp);
800
801             treeview_insert(&tvfaff, 1, "Keyboard");
802         }
803
804         /* The Window panel. Accelerators used: [acgo] bsdkw4ylpt */
805         {
806             struct ctlpos cp;
807             ctlposinit(&cp, hwnd, 80, 3, 13);
808             bartitle(&cp, "Options controlling PuTTY's window",
809                      IDC_TITLE_WINDOW);
810             beginbox(&cp, "Set the size of the window",
811                      IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
812             multiedit(&cp,
813                       "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
814                       "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
815                       NULL);
816             checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
817             endbox(&cp);
818             beginbox(&cp, "Control the scrollback in the window",
819                      IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
820             staticedit(&cp, "Lines of &scrollback",
821                        IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
822             checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
823             checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
824             checkbox(&cp, "Reset scrollback on dis&play activity",
825                      IDC_SCROLLDISP);
826             endbox(&cp);
827             beginbox(&cp, NULL, IDC_BOX_WINDOW3, 0);
828             checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
829             checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
830             checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
831             checkbox(&cp, "System menu appears on A&LT alone", IDC_ALTONLY);
832             checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
833             endbox(&cp);
834
835             treeview_insert(&tvfaff, 0, "Window");
836         }
837
838         /* The Appearance panel. Accelerators used: [acgo] rmkhtibluv */
839         {
840             struct ctlpos cp;
841             ctlposinit(&cp, hwnd, 80, 3, 13);
842             bartitle(&cp, "Options controlling PuTTY's appearance",
843                      IDC_TITLE_APPEARANCE);
844             beginbox(&cp, "Adjust the use of the cursor",
845                      IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1);
846             radioline(&cp, "Cursor appearance:", IDC_CURSTATIC, 3,
847                       "B&lock", IDC_CURBLOCK,
848                       "&Underline", IDC_CURUNDER,
849                       "&Vertical line", IDC_CURVERT,
850                       NULL);
851             checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
852             endbox(&cp);
853             beginbox(&cp, "Set the font used in the terminal window",
854                      IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2);
855             staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
856             endbox(&cp);
857             beginbox(&cp, "Adjust the use of the window title",
858                      IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3);
859             multiedit(&cp,
860                       "Window &title:", IDC_WINTITLE,
861                       IDC_WINEDIT, 100, NULL);
862             checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
863             endbox(&cp);
864
865             treeview_insert(&tvfaff, 1, "Appearance");
866         }
867
868         /* The Translation panel. Accelerators used: [acgo] xbepnkis */
869         {
870             struct ctlpos cp;
871             ctlposinit(&cp, hwnd, 80, 3, 13);
872             bartitle(&cp, "Options controlling character set translation",
873                      IDC_TITLE_TRANSLATION);
874             beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
875                      IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
876             radiobig(&cp,
877                      "Handling of line drawing characters:", IDC_VTSTATIC,
878                      "Font has &XWindows encoding", IDC_VTXWINDOWS,
879                      "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
880                      "Use font in O&EM mode only", IDC_VTOEMONLY,
881                      "&Poor man's line drawing (""+"", ""-"" and ""|"")",
882                      IDC_VTPOORMAN, NULL);
883             endbox(&cp);
884             beginbox(&cp, "Enable character set translation on received data",
885                      IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
886             radiobig(&cp,
887                      "Character set translation:", IDC_XLATSTATIC,
888                      "&None", IDC_NOXLAT,
889                      "&KOI8 / Win-1251", IDC_KOI8WIN1251,
890                      "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
891                      "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
892             endbox(&cp);
893             beginbox(&cp, "Enable character set translation on input data",
894                      IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
895             checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
896                      IDC_CAPSLOCKCYR);
897             endbox(&cp);
898
899             treeview_insert(&tvfaff, 1, "Translation");
900         }
901
902         /* The Selection panel. Accelerators used: [acgo] wxst */
903         {
904             struct ctlpos cp;
905             ctlposinit(&cp, hwnd, 80, 3, 13);
906             bartitle(&cp, "Options controlling copy and paste",
907                      IDC_TITLE_SELECTION);
908             beginbox(&cp, "Control which mouse button does which thing",
909                      IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
910             radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
911                      "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
912                      "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
913                      NULL);
914             endbox(&cp);
915             beginbox(&cp, "Control the select-one-word-at-a-time mode",
916                      IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
917             charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
918                       "&Set", IDC_CCSET, IDC_CCEDIT,
919                       "&to class", IDC_CCSTATIC2);
920             endbox(&cp);
921
922             treeview_insert(&tvfaff, 1, "Selection");
923         }
924
925         /* The Colours panel. Accelerators used: [acgo] blum */
926         {
927             struct ctlpos cp;
928             ctlposinit(&cp, hwnd, 80, 3, 13);
929             bartitle(&cp, "Options controlling use of colours",
930                      IDC_TITLE_COLOURS);
931             beginbox(&cp, "General options for colour usage",
932                      IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
933             checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
934             checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
935             endbox(&cp);
936             beginbox(&cp, "Adjust the precise colours PuTTY displays",
937                      IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
938             colouredit(&cp, "Select a colo&ur and then click to modify it:",
939                        IDC_COLOURSTATIC, IDC_COLOURLIST,
940                        "&Modify...", IDC_CHANGE,
941                        "Red:", IDC_RSTATIC, IDC_RVALUE,
942                        "Green:", IDC_GSTATIC, IDC_GVALUE,
943                        "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
944             endbox(&cp);
945
946             treeview_insert(&tvfaff, 1, "Colours");
947         }
948
949         /* The Connection panel. Accelerators used: [acgo] tuk */
950         {
951             struct ctlpos cp;
952             ctlposinit(&cp, hwnd, 80, 3, 13);
953             bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
954             if (dlgtype == 0) {
955                 beginbox(&cp, "Data to send to the server",
956                          IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
957                 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
958                 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
959                 endbox(&cp);
960             }
961             beginbox(&cp, "Sending of null packets to keep session active",
962                      IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
963             staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
964                        IDC_PINGSTATIC, IDC_PINGEDIT, 25);
965             endbox(&cp);
966
967             treeview_insert(&tvfaff, 0, "Connection");
968         }
969
970         /* The Telnet panel. Accelerators used: [acgo] svldrbf */
971         {
972             struct ctlpos cp;
973             ctlposinit(&cp, hwnd, 80, 3, 13);
974             if (dlgtype == 0) {
975                 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
976                 beginbox(&cp, "Data to send to the server",
977                          IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
978                 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
979                 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
980                           "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
981                           "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
982                           IDC_ENVLIST,
983                           "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
984                 endbox(&cp);
985                 beginbox(&cp, "Telnet protocol adjustments",
986                          IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
987                 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
988                           "&BSD (commonplace)", IDC_EMBSD,
989                           "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
990                 endbox(&cp);
991
992                 treeview_insert(&tvfaff, 1, "Telnet");
993             }
994         }
995
996         /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
997         if (backends[2].backend != NULL) {
998             struct ctlpos cp;
999             ctlposinit(&cp, hwnd, 80, 3, 13);
1000             if (dlgtype == 0) {
1001                 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1002                 beginbox(&cp, "Data to send to the server",
1003                          IDC_BOX_SSH1, IDC_BOXT_SSH1);
1004                 multiedit(&cp,
1005                           "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1006                           NULL);
1007                 endbox(&cp);
1008                 beginbox(&cp, "Authentication options",
1009                          IDC_BOX_SSH2, IDC_BOXT_SSH2);
1010                 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1011                          IDC_AUTHTIS);
1012                 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1013                 editbutton(&cp, "Private &key file for authentication:",
1014                            IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1015                 endbox(&cp);
1016                 beginbox(&cp, "Protocol options",
1017                          IDC_BOX_SSH3, IDC_BOXT_SSH3);
1018                 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1019                 checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
1020                 radioline(&cp, "Preferred SSH protocol version:",
1021                           IDC_SSHPROTSTATIC, 2,
1022                           "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1023                 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1024                           "&3DES", IDC_CIPHER3DES,
1025                           "&Blowfish", IDC_CIPHERBLOWF,
1026                           "&DES", IDC_CIPHERDES, NULL);
1027                 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1028                          IDC_BUGGYMAC);
1029                 endbox(&cp);
1030
1031                 treeview_insert(&tvfaff, 1, "SSH");
1032             }
1033         }
1034
1035         init_dlg_ctrls(hwnd);
1036         for (i = 0; i < nsessions; i++)
1037             SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1038                                 0, (LPARAM) (sessions[i]));
1039
1040         /*
1041          * Hide all the controls to start with.
1042          */
1043         hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1044
1045         /*
1046          * Put the treeview selection on to the Session panel. This
1047          * should also cause unhiding of the relevant controls.
1048          */
1049         TreeView_SelectItem(treeview, hsession);
1050
1051         /*
1052          * Set focus into the first available control.
1053          */
1054         {
1055             HWND ctl;
1056             ctl = GetDlgItem(hwnd, IDC_HOST);
1057             if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1058             SetFocus(ctl);
1059         }
1060
1061         SetWindowLong(hwnd, GWL_USERDATA, 1);
1062         return 0;
1063       case WM_LBUTTONUP:
1064         /*
1065          * Button release should trigger WM_OK if there was a
1066          * previous double click on the session list.
1067          */
1068         ReleaseCapture();
1069         if (readytogo)
1070             SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1071         break;
1072       case WM_NOTIFY:
1073         if (LOWORD(wParam) == IDCX_TREEVIEW &&
1074             ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1075             HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1076             TVITEM item;
1077             char buffer[64];
1078             item.hItem = i;
1079             item.pszText = buffer;
1080             item.cchTextMax = sizeof(buffer);
1081             item.mask = TVIF_TEXT;
1082             TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1083             hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1084             if (!strcmp(buffer, "Session"))
1085                 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1086             if (!strcmp(buffer, "Keyboard"))
1087                 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1088             if (!strcmp(buffer, "Terminal"))
1089                 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1090             if (!strcmp(buffer, "Window"))
1091                 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1092             if (!strcmp(buffer, "Appearance"))
1093                 hide(hwnd, FALSE, appearancepanelstart, appearancepanelend);
1094             if (!strcmp(buffer, "Connection"))
1095                 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1096             if (!strcmp(buffer, "Telnet"))
1097                 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1098             if (!strcmp(buffer, "SSH"))
1099                 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1100             if (!strcmp(buffer, "Selection"))
1101                 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1102             if (!strcmp(buffer, "Colours"))
1103                 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1104             if (!strcmp(buffer, "Translation"))
1105                 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1106
1107             SetFocus (((LPNMHDR)lParam)->hwndFrom);   /* ensure focus stays */
1108             return 0;
1109         }
1110         break;
1111       case WM_COMMAND:
1112         /*
1113          * Only process WM_COMMAND once the dialog is fully formed.
1114          */
1115         if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1116           case IDOK:
1117             if (*cfg.host)
1118                 EndDialog (hwnd, 1);
1119             else
1120                 MessageBeep (0);
1121             return 0;
1122           case IDCANCEL:
1123             EndDialog (hwnd, 0);
1124             return 0;
1125           case IDC_PROTTELNET:
1126           case IDC_PROTSSH:
1127           case IDC_PROTRAW:
1128             if (HIWORD(wParam) == BN_CLICKED ||
1129                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1130                 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1131                 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1132                 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1133                 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1134                     (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1135                     cfg.port = i ? 22 : 23;
1136                     SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1137                 }
1138             }
1139             break;
1140           case IDC_HOST:
1141             if (HIWORD(wParam) == EN_CHANGE)
1142                 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1143                                 sizeof(cfg.host)-1);
1144             break;
1145           case IDC_PORT:
1146             if (HIWORD(wParam) == EN_CHANGE) {
1147                 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1148                 if (isdigit(portname[0]))
1149                     MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1150                 else {
1151                     service = getservbyname(portname, NULL);
1152                     if (service) cfg.port = ntohs(service->s_port);
1153                     else cfg.port = 0;
1154                 }
1155             }
1156             break;
1157           case IDC_SESSEDIT:
1158             if (HIWORD(wParam) == EN_CHANGE) {
1159                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1160                                     (WPARAM) -1, 0);
1161                 GetDlgItemText (hwnd, IDC_SESSEDIT,
1162                                 savedsession, sizeof(savedsession)-1);
1163                 savedsession[sizeof(savedsession)-1] = '\0';
1164             }
1165             break;
1166           case IDC_SESSSAVE:
1167             if (HIWORD(wParam) == BN_CLICKED ||
1168                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1169                 /*
1170                  * Save a session
1171                  */
1172                 char str[2048];
1173                 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1174                 if (!*str) {
1175                     int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1176                                                 LB_GETCURSEL, 0, 0);
1177                     if (n == LB_ERR) {
1178                         MessageBeep(0);
1179                         break;
1180                     }
1181                     strcpy (str, sessions[n]);
1182                 }
1183                 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1184                 get_sesslist (FALSE);
1185                 get_sesslist (TRUE);
1186                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1187                                     0, 0);
1188                 for (i = 0; i < nsessions; i++)
1189                     SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1190                                         0, (LPARAM) (sessions[i]));
1191                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1192                                     (WPARAM) -1, 0);
1193             }
1194             break;
1195           case IDC_SESSLIST:
1196           case IDC_SESSLOAD:
1197             if (LOWORD(wParam) == IDC_SESSLOAD &&
1198                 HIWORD(wParam) != BN_CLICKED &&
1199                 HIWORD(wParam) != BN_DOUBLECLICKED)
1200                 break;
1201             if (LOWORD(wParam) == IDC_SESSLIST &&
1202                 HIWORD(wParam) != LBN_DBLCLK)
1203                 break;
1204             {
1205                 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1206                                             LB_GETCURSEL, 0, 0);
1207                 int isdef;
1208                 if (n == LB_ERR) {
1209                     MessageBeep(0);
1210                     break;
1211                 }
1212                 isdef = !strcmp(sessions[n], "Default Settings");
1213                 load_settings (sessions[n], !isdef, &cfg);
1214                 init_dlg_ctrls(hwnd);
1215                 if (!isdef)
1216                     SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1217                 else
1218                     SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1219             }
1220             if (LOWORD(wParam) == IDC_SESSLIST) {
1221                 /*
1222                  * A double-click on a saved session should
1223                  * actually start the session, not just load it.
1224                  * Unless it's Default Settings or some other
1225                  * host-less set of saved settings.
1226                  */
1227                 if (*cfg.host) {
1228                     readytogo = TRUE;
1229                     SetCapture(hwnd);
1230                 }
1231             }
1232             break;
1233           case IDC_SESSDEL:
1234             if (HIWORD(wParam) == BN_CLICKED ||
1235                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1236                 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1237                                             LB_GETCURSEL, 0, 0);
1238                 if (n == LB_ERR || n == 0) {
1239                     MessageBeep(0);
1240                     break;
1241                 }
1242                 del_settings(sessions[n]);
1243                 get_sesslist (FALSE);
1244                 get_sesslist (TRUE);
1245                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1246                                     0, 0);
1247                 for (i = 0; i < nsessions; i++)
1248                     SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1249                                         0, (LPARAM) (sessions[i]));
1250                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1251                                     (WPARAM) -1, 0);
1252             }
1253           case IDC_PINGEDIT:
1254             if (HIWORD(wParam) == EN_CHANGE)
1255                 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1256             break;
1257           case IDC_DEL008:
1258           case IDC_DEL127:
1259             if (HIWORD(wParam) == BN_CLICKED ||
1260                 HIWORD(wParam) == BN_DOUBLECLICKED)
1261                 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1262             break;
1263           case IDC_HOMETILDE:
1264           case IDC_HOMERXVT:
1265             if (HIWORD(wParam) == BN_CLICKED ||
1266                 HIWORD(wParam) == BN_DOUBLECLICKED)
1267                 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1268             break;
1269           case IDC_FUNCXTERM:
1270             if (HIWORD(wParam) == BN_CLICKED ||
1271                 HIWORD(wParam) == BN_DOUBLECLICKED)
1272                 cfg.funky_type = 2;
1273             break;
1274           case IDC_FUNCVT400:
1275             if (HIWORD(wParam) == BN_CLICKED ||
1276                 HIWORD(wParam) == BN_DOUBLECLICKED)
1277                 cfg.funky_type = 3;
1278             break;
1279           case IDC_FUNCTILDE:
1280           case IDC_FUNCLINUX:
1281             if (HIWORD(wParam) == BN_CLICKED ||
1282                 HIWORD(wParam) == BN_DOUBLECLICKED)
1283                 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1284             break;
1285           case IDC_KPNORMAL:
1286           case IDC_KPAPPLIC:
1287             if (HIWORD(wParam) == BN_CLICKED ||
1288                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1289                 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1290                 cfg.nethack_keypad = FALSE;
1291             }
1292             break;
1293           case IDC_KPNH:
1294             if (HIWORD(wParam) == BN_CLICKED ||
1295                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1296                 cfg.app_keypad = FALSE;
1297                 cfg.nethack_keypad = TRUE;
1298             }
1299             break;
1300           case IDC_CURNORMAL:
1301           case IDC_CURAPPLIC:
1302             if (HIWORD(wParam) == BN_CLICKED ||
1303                 HIWORD(wParam) == BN_DOUBLECLICKED)
1304                 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1305             break;
1306           case IDC_NOAPPLICC:
1307             if (HIWORD(wParam) == BN_CLICKED ||
1308                 HIWORD(wParam) == BN_DOUBLECLICKED)
1309                 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1310             break;
1311           case IDC_NOAPPLICK:
1312             if (HIWORD(wParam) == BN_CLICKED ||
1313                 HIWORD(wParam) == BN_DOUBLECLICKED)
1314                 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1315             break;
1316           case IDC_ALTF4:
1317             if (HIWORD(wParam) == BN_CLICKED ||
1318                 HIWORD(wParam) == BN_DOUBLECLICKED)
1319                 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1320             break;
1321           case IDC_ALTSPACE:
1322             if (HIWORD(wParam) == BN_CLICKED ||
1323                 HIWORD(wParam) == BN_DOUBLECLICKED)
1324                 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1325             break;
1326           case IDC_ALTONLY:
1327             if (HIWORD(wParam) == BN_CLICKED ||
1328                 HIWORD(wParam) == BN_DOUBLECLICKED)
1329                 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1330             break;
1331           case IDC_LDISCTERM:
1332             if (HIWORD(wParam) == BN_CLICKED ||
1333                 HIWORD(wParam) == BN_DOUBLECLICKED)
1334                 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1335             break;
1336           case IDC_ALWAYSONTOP:
1337             if (HIWORD(wParam) == BN_CLICKED ||
1338                 HIWORD(wParam) == BN_DOUBLECLICKED)
1339                 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1340             break;
1341           case IDC_SCROLLKEY:
1342             if (HIWORD(wParam) == BN_CLICKED ||
1343                 HIWORD(wParam) == BN_DOUBLECLICKED)
1344                 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1345             break;
1346           case IDC_SCROLLDISP:
1347             if (HIWORD(wParam) == BN_CLICKED ||
1348                 HIWORD(wParam) == BN_DOUBLECLICKED)
1349                 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1350             break;
1351           case IDC_COMPOSEKEY:
1352             if (HIWORD(wParam) == BN_CLICKED ||
1353                 HIWORD(wParam) == BN_DOUBLECLICKED)
1354                 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1355             break;
1356           case IDC_WRAPMODE:
1357             if (HIWORD(wParam) == BN_CLICKED ||
1358                 HIWORD(wParam) == BN_DOUBLECLICKED)
1359                 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1360             break;
1361           case IDC_DECOM:
1362             if (HIWORD(wParam) == BN_CLICKED ||
1363                 HIWORD(wParam) == BN_DOUBLECLICKED)
1364                 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1365             break;
1366           case IDC_LFHASCR:
1367             if (HIWORD(wParam) == BN_CLICKED ||
1368                 HIWORD(wParam) == BN_DOUBLECLICKED)
1369                 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1370             break;
1371           case IDC_ROWSEDIT:
1372             if (HIWORD(wParam) == EN_CHANGE)
1373                 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1374             break;
1375           case IDC_COLSEDIT:
1376             if (HIWORD(wParam) == EN_CHANGE)
1377                 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1378             break;
1379           case IDC_SAVEEDIT:
1380             if (HIWORD(wParam) == EN_CHANGE)
1381                 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1382             break;
1383           case IDC_CHOOSEFONT:
1384             lf.lfHeight = cfg.fontheight;
1385             lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1386             lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1387             lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1388             lf.lfCharSet = cfg.fontcharset;
1389             lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1390             lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1391             lf.lfQuality = DEFAULT_QUALITY;
1392             lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1393             strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1394             lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1395
1396             cf.lStructSize = sizeof(cf);
1397             cf.hwndOwner = hwnd;
1398             cf.lpLogFont = &lf;
1399             cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1400                 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1401
1402             if (ChooseFont (&cf)) {
1403                 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1404                 cfg.font[sizeof(cfg.font)-1] = '\0';
1405                 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1406                 cfg.fontcharset = lf.lfCharSet;
1407                 cfg.fontheight = lf.lfHeight;
1408                 fmtfont (fontstatic);
1409                 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1410             }
1411             break;
1412           case IDC_BEEP:
1413             if (HIWORD(wParam) == BN_CLICKED ||
1414                 HIWORD(wParam) == BN_DOUBLECLICKED)
1415                 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1416             break;
1417           case IDC_BLINKTEXT:
1418             if (HIWORD(wParam) == BN_CLICKED ||
1419                 HIWORD(wParam) == BN_DOUBLECLICKED)
1420                 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1421             break;
1422           case IDC_BCE:
1423             if (HIWORD(wParam) == BN_CLICKED ||
1424                 HIWORD(wParam) == BN_DOUBLECLICKED)
1425                 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1426             break;
1427           case IDC_WINNAME:
1428             if (HIWORD(wParam) == BN_CLICKED ||
1429                 HIWORD(wParam) == BN_DOUBLECLICKED)
1430                 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1431             break;
1432           case IDC_CURBLOCK:
1433             if (HIWORD(wParam) == BN_CLICKED ||
1434                 HIWORD(wParam) == BN_DOUBLECLICKED)
1435                 cfg.cursor_type = 0;
1436             break;
1437           case IDC_CURUNDER:
1438             if (HIWORD(wParam) == BN_CLICKED ||
1439                 HIWORD(wParam) == BN_DOUBLECLICKED)
1440                 cfg.cursor_type = 1;
1441             break;
1442           case IDC_CURVERT:
1443             if (HIWORD(wParam) == BN_CLICKED ||
1444                 HIWORD(wParam) == BN_DOUBLECLICKED)
1445                 cfg.cursor_type = 2;
1446             break;
1447           case IDC_BLINKCUR:
1448             if (HIWORD(wParam) == BN_CLICKED ||
1449                 HIWORD(wParam) == BN_DOUBLECLICKED)
1450                 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1451             break;
1452           case IDC_SCROLLBAR:
1453             if (HIWORD(wParam) == BN_CLICKED ||
1454                 HIWORD(wParam) == BN_DOUBLECLICKED)
1455                 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1456             break;
1457           case IDC_LOCKSIZE:
1458              if (HIWORD(wParam) == BN_CLICKED ||
1459                  HIWORD(wParam) == BN_DOUBLECLICKED)
1460                 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1461             break;
1462           case IDC_WINEDIT:
1463             if (HIWORD(wParam) == EN_CHANGE)
1464                 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1465                                 sizeof(cfg.wintitle)-1);
1466             break;
1467           case IDC_CLOSEEXIT:
1468             if (HIWORD(wParam) == BN_CLICKED ||
1469                 HIWORD(wParam) == BN_DOUBLECLICKED)
1470                 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1471             break;
1472           case IDC_CLOSEWARN:
1473             if (HIWORD(wParam) == BN_CLICKED ||
1474                 HIWORD(wParam) == BN_DOUBLECLICKED)
1475                 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1476             break;
1477           case IDC_TTEDIT:
1478             if (HIWORD(wParam) == EN_CHANGE)
1479             GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1480                             sizeof(cfg.termtype)-1);
1481             break;
1482           case IDC_LGFEDIT:
1483             if (HIWORD(wParam) == EN_CHANGE)
1484             GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1485                             sizeof(cfg.logfilename)-1);
1486             break;
1487           case IDC_LGFBUTTON:
1488             memset(&of, 0, sizeof(of));
1489 #ifdef OPENFILENAME_SIZE_VERSION_400
1490             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1491 #else
1492             of.lStructSize = sizeof(of);
1493 #endif
1494             of.hwndOwner = hwnd;
1495             of.lpstrFilter = "All Files\0*\0\0\0";
1496             of.lpstrCustomFilter = NULL;
1497             of.nFilterIndex = 1;
1498             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1499             of.nMaxFile = sizeof(filename);
1500             of.lpstrFileTitle = NULL;
1501             of.lpstrInitialDir = NULL;
1502             of.lpstrTitle = "Select session log file";
1503             of.Flags = 0;
1504             if (GetSaveFileName(&of)) {
1505                 strcpy(cfg.keyfile, filename);
1506                 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
1507             }
1508             break;
1509           case IDC_LSTATOFF:
1510           case IDC_LSTATASCII:
1511           case IDC_LSTATRAW:
1512             if (HIWORD(wParam) == BN_CLICKED ||
1513                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1514                 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1515                 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1516                 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1517             }
1518             break;
1519           case IDC_TSEDIT:
1520             if (HIWORD(wParam) == EN_CHANGE)
1521                 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1522                                 sizeof(cfg.termspeed)-1);
1523             break;
1524           case IDC_LOGEDIT:
1525             if (HIWORD(wParam) == EN_CHANGE)
1526                 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1527                                 sizeof(cfg.username)-1);
1528             break;
1529           case IDC_EMBSD:
1530           case IDC_EMRFC:
1531             cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1532             break;
1533           case IDC_ENVADD:
1534             if (HIWORD(wParam) == BN_CLICKED ||
1535                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1536               char str[sizeof(cfg.environmt)];
1537                 char *p;
1538                 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1539                 if (!*str) {
1540                     MessageBeep(0);
1541                     break;
1542                 }
1543                 p = str + strlen(str);
1544                 *p++ = '\t';
1545                 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1546                 if (!*p) {
1547                     MessageBeep(0);
1548                     break;
1549                 }
1550               p = cfg.environmt;
1551                 while (*p) {
1552                     while (*p) p++;
1553                     p++;
1554                 }
1555               if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1556                     strcpy (p, str);
1557                     p[strlen(str)+1] = '\0';
1558                     SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1559                                         0, (LPARAM)str);
1560                     SetDlgItemText (hwnd, IDC_VAREDIT, "");
1561                     SetDlgItemText (hwnd, IDC_VALEDIT, "");
1562                 } else {
1563                     MessageBox(hwnd, "Environment too big", "PuTTY Error",
1564                                MB_OK | MB_ICONERROR);
1565                 }
1566             }
1567             break;
1568           case IDC_ENVREMOVE:
1569             if (HIWORD(wParam) != BN_CLICKED &&
1570                 HIWORD(wParam) != BN_DOUBLECLICKED)
1571                 break;
1572             i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1573             if (i == LB_ERR)
1574                 MessageBeep (0);
1575             else {
1576                 char *p, *q;
1577
1578                 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1579                                     i, 0);
1580               p = cfg.environmt;
1581                 while (i > 0) {
1582                     if (!*p)
1583                         goto disaster;
1584                     while (*p) p++;
1585                     p++;
1586                     i--;
1587                 }
1588                 q = p;
1589                 if (!*p)
1590                     goto disaster;
1591                 while (*p) p++;
1592                 p++;
1593                 while (*p) {
1594                     while (*p)
1595                         *q++ = *p++;
1596                     *q++ = *p++;
1597                 }
1598                 *q = '\0';
1599                 disaster:;
1600             }
1601             break;
1602           case IDC_NOPTY:
1603             if (HIWORD(wParam) == BN_CLICKED ||
1604                 HIWORD(wParam) == BN_DOUBLECLICKED)
1605                 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1606             break;
1607           case IDC_COMPRESS:
1608             if (HIWORD(wParam) == BN_CLICKED ||
1609                 HIWORD(wParam) == BN_DOUBLECLICKED)
1610                 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1611             break;
1612           case IDC_BUGGYMAC:
1613             if (HIWORD(wParam) == BN_CLICKED ||
1614                 HIWORD(wParam) == BN_DOUBLECLICKED)
1615                 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1616             break;
1617           case IDC_AGENTFWD:
1618             if (HIWORD(wParam) == BN_CLICKED ||
1619                 HIWORD(wParam) == BN_DOUBLECLICKED)
1620                 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1621             break;
1622           case IDC_CIPHER3DES:
1623           case IDC_CIPHERBLOWF:
1624           case IDC_CIPHERDES:
1625             if (HIWORD(wParam) == BN_CLICKED ||
1626                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1627                 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1628                     cfg.cipher = CIPHER_3DES;
1629                 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1630                     cfg.cipher = CIPHER_BLOWFISH;
1631                 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1632                     cfg.cipher = CIPHER_DES;
1633             }
1634             break;
1635           case IDC_SSHPROT1:
1636           case IDC_SSHPROT2:
1637             if (HIWORD(wParam) == BN_CLICKED ||
1638                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1639                 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1640                     cfg.sshprot = 1;
1641                 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1642                     cfg.sshprot = 2;
1643             }
1644             break;
1645           case IDC_AUTHTIS:
1646             if (HIWORD(wParam) == BN_CLICKED ||
1647                 HIWORD(wParam) == BN_DOUBLECLICKED)
1648                 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1649             break;
1650           case IDC_PKEDIT:
1651             if (HIWORD(wParam) == EN_CHANGE)
1652                 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1653                                 sizeof(cfg.keyfile)-1);
1654             break;
1655           case IDC_CMDEDIT:
1656             if (HIWORD(wParam) == EN_CHANGE)
1657                 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1658                                 sizeof(cfg.remote_cmd)-1);
1659             break;
1660           case IDC_PKBUTTON:
1661             memset(&of, 0, sizeof(of));
1662 #ifdef OPENFILENAME_SIZE_VERSION_400
1663             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1664 #else
1665             of.lStructSize = sizeof(of);
1666 #endif
1667             of.hwndOwner = hwnd;
1668             of.lpstrFilter = "All Files\0*\0\0\0";
1669             of.lpstrCustomFilter = NULL;
1670             of.nFilterIndex = 1;
1671             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1672             of.nMaxFile = sizeof(filename);
1673             of.lpstrFileTitle = NULL;
1674             of.lpstrInitialDir = NULL;
1675             of.lpstrTitle = "Select Public Key File";
1676             of.Flags = 0;
1677             if (GetOpenFileName(&of)) {
1678                 strcpy(cfg.keyfile, filename);
1679                 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1680             }
1681             break;
1682           case IDC_MBWINDOWS:
1683           case IDC_MBXTERM:
1684             cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1685             break;
1686           case IDC_CCSET:
1687             {
1688                 BOOL ok;
1689                 int i;
1690                 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1691
1692                 if (!ok)
1693                     MessageBeep (0);
1694                 else {
1695                     for (i=0; i<256; i++)
1696                         if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1697                                                 i, 0)) {
1698                             char str[100];
1699                             cfg.wordness[i] = n;
1700                             SendDlgItemMessage (hwnd, IDC_CCLIST,
1701                                                 LB_DELETESTRING, i, 0);
1702                             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1703                                     (i>=0x21 && i != 0x7F) ? i : ' ',
1704                                     cfg.wordness[i]);
1705                             SendDlgItemMessage (hwnd, IDC_CCLIST,
1706                                                 LB_INSERTSTRING, i,
1707                                                 (LPARAM)str);
1708                         }
1709                 }
1710             }
1711             break;
1712           case IDC_BOLDCOLOUR:
1713             if (HIWORD(wParam) == BN_CLICKED ||
1714                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1715                 int n, i;
1716                 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1717                 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1718                 if (n != 12+10*cfg.bold_colour) {
1719                     for (i=n; i-- >0 ;)
1720                         SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1721                                                 LB_DELETESTRING, i, 0);
1722                     for (i=0; i<22; i++)
1723                         if (cfg.bold_colour || permcolour[i])
1724                             SendDlgItemMessage (hwnd, IDC_COLOURLIST, 
1725                                                 LB_ADDSTRING, 0,
1726                                                 (LPARAM) colours[i]);
1727                 }
1728             }
1729             break;
1730           case IDC_PALETTE:
1731             if (HIWORD(wParam) == BN_CLICKED ||
1732                 HIWORD(wParam) == BN_DOUBLECLICKED)
1733                 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1734             break;
1735           case IDC_COLOURLIST:
1736             if (HIWORD(wParam) == LBN_DBLCLK ||
1737                 HIWORD(wParam) == LBN_SELCHANGE) {
1738                 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1739                                             0, 0);
1740                 if (!cfg.bold_colour)
1741                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1742                 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1743                 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1744                 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1745             }
1746             break;
1747           case IDC_CHANGE:
1748             if (HIWORD(wParam) == BN_CLICKED ||
1749                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1750                 static CHOOSECOLOR cc;
1751                 static DWORD custom[16] = {0};   /* zero initialisers */
1752                 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1753                                             0, 0);
1754                 if (!cfg.bold_colour)
1755                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1756                 cc.lStructSize = sizeof(cc);
1757                 cc.hwndOwner = hwnd;
1758                 cc.hInstance = (HWND)hinst;
1759                 cc.lpCustColors = custom;
1760                 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1761                                     cfg.colours[i][2]);
1762                 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1763                 if (ChooseColor(&cc)) {
1764                     cfg.colours[i][0] =
1765                         (unsigned char) (cc.rgbResult & 0xFF);
1766                     cfg.colours[i][1] =
1767                         (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1768                     cfg.colours[i][2] =
1769                         (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1770                     SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1771                                    FALSE);
1772                     SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1773                                    FALSE);
1774                     SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1775                                    FALSE);
1776                 }
1777             }
1778             break;
1779           case IDC_NOXLAT:
1780           case IDC_KOI8WIN1251:
1781           case IDC_88592WIN1250:
1782           case IDC_88592CP852:
1783             cfg.xlat_enablekoiwin =
1784                 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1785             cfg.xlat_88592w1250 =
1786                 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1787             cfg.xlat_88592cp852 =
1788                 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1789             break;
1790           case IDC_CAPSLOCKCYR:
1791             if (HIWORD(wParam) == BN_CLICKED ||
1792                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1793                 cfg.xlat_capslockcyr =
1794                     IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1795             }
1796             break;
1797           case IDC_VTXWINDOWS:
1798           case IDC_VTOEMANSI:
1799           case IDC_VTOEMONLY:
1800           case IDC_VTPOORMAN:
1801             cfg.vtmode =
1802                 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1803                  IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1804                  IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1805                  VT_POORMAN);
1806             break;
1807         }
1808         return 0;
1809       case WM_CLOSE:
1810         EndDialog (hwnd, 0);
1811         return 0;
1812
1813         /* Grrr Explorer will maximize Dialogs! */
1814       case WM_SIZE:
1815         if (wParam == SIZE_MAXIMIZED)
1816            force_normal(hwnd);
1817         return 0;
1818     }
1819     return 0;
1820 }
1821
1822 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1823                                  WPARAM wParam, LPARAM lParam) {
1824     static HWND page = NULL;
1825
1826     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1827     }
1828     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1829         EnableWindow(hwnd, 0);
1830         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1831                   GetParent(hwnd), AboutProc);
1832         EnableWindow(hwnd, 1);
1833         SetActiveWindow(hwnd);
1834     }
1835     return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1836 }
1837
1838 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1839                                    WPARAM wParam, LPARAM lParam) {
1840     static HWND page;
1841     return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1842 }
1843
1844 void defuse_showwindow(void) {
1845     /*
1846      * Work around the fact that the app's first call to ShowWindow
1847      * will ignore the default in favour of the shell-provided
1848      * setting.
1849      */
1850     {
1851         HWND hwnd;
1852         hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1853                              NULL, NullDlgProc);
1854         ShowWindow(hwnd, SW_HIDE);
1855         DestroyWindow(hwnd);
1856     }
1857 }
1858
1859 int do_config (void) {
1860     int ret;
1861
1862     get_sesslist(TRUE);
1863     savedsession[0] = '\0';
1864     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1865     get_sesslist(FALSE);
1866
1867     return ret;
1868 }
1869
1870 int do_reconfig (HWND hwnd) {
1871     Config backup_cfg;
1872     int ret;
1873
1874     backup_cfg = cfg;                  /* structure copy */
1875     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1876     if (!ret)
1877         cfg = backup_cfg;              /* structure copy */
1878
1879     return ret;
1880 }
1881
1882 void logevent (char *string) {
1883     if (nevents >= negsize) {
1884         negsize += 64;
1885         events = srealloc (events, negsize * sizeof(*events));
1886     }
1887     events[nevents] = smalloc(1+strlen(string));
1888     strcpy (events[nevents], string);
1889     nevents++;
1890     if (logbox) {
1891         int count;
1892         SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1893                             0, (LPARAM)string);
1894         count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1895         SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1896     }
1897 }
1898
1899 void showeventlog (HWND hwnd) {
1900     if (!logbox) {
1901         logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1902                                hwnd, LogProc);
1903         ShowWindow (logbox, SW_SHOWNORMAL);
1904     }
1905 }
1906
1907 void showabout (HWND hwnd) {
1908     if (!abtbox) {
1909         abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1910                                hwnd, AboutProc);
1911         ShowWindow (abtbox, SW_SHOWNORMAL);
1912     }
1913 }
1914
1915 void verify_ssh_host_key(char *host, int port, char *keytype,
1916                          char *keystr, char *fingerprint) {
1917     int ret;
1918
1919     static const char absentmsg[] =
1920         "The server's host key is not cached in the registry. You\n"
1921         "have no guarantee that the server is the computer you\n"
1922         "think it is.\n"
1923         "The server's key fingerprint is:\n"
1924         "%s\n"
1925         "If you trust this host, hit Yes to add the key to\n"
1926         "PuTTY's cache and carry on connecting.\n"
1927         "If you do not trust this host, hit No to abandon the\n"
1928         "connection.\n";
1929
1930     static const char wrongmsg[] =
1931         "WARNING - POTENTIAL SECURITY BREACH!\n"
1932         "\n"
1933         "The server's host key does not match the one PuTTY has\n"
1934         "cached in the registry. This means that either the\n"
1935         "server administrator has changed the host key, or you\n"
1936         "have actually connected to another computer pretending\n"
1937         "to be the server.\n"
1938         "The new key fingerprint is:\n"
1939         "%s\n"
1940         "If you were expecting this change and trust the new key,\n"
1941         "hit Yes to update PuTTY's cache and continue connecting.\n"
1942         "If you want to carry on connecting but without updating\n"
1943         "the cache, hit No.\n"
1944         "If you want to abandon the connection completely, hit\n"
1945         "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1946         "choice.\n";
1947
1948     static const char mbtitle[] = "PuTTY Security Alert";
1949
1950     
1951     char message[160+                  /* sensible fingerprint max size */
1952                  (sizeof(absentmsg) > sizeof(wrongmsg) ?
1953                   sizeof(absentmsg) : sizeof(wrongmsg))];
1954
1955     /*
1956      * Verify the key against the registry.
1957      */
1958     ret = verify_host_key(host, port, keytype, keystr);
1959
1960     if (ret == 0)                      /* success - key matched OK */
1961         return;
1962     if (ret == 2) {                    /* key was different */
1963         int mbret;
1964         sprintf(message, wrongmsg, fingerprint);
1965         mbret = MessageBox(NULL, message, mbtitle,
1966                            MB_ICONWARNING | MB_YESNOCANCEL);
1967         if (mbret == IDYES)
1968             store_host_key(host, port, keytype, keystr);
1969         if (mbret == IDCANCEL)
1970             exit(0);
1971     }
1972     if (ret == 1) {                    /* key was absent */
1973         int mbret;
1974         sprintf(message, absentmsg, fingerprint);
1975         mbret = MessageBox(NULL, message, mbtitle,
1976                            MB_ICONWARNING | MB_YESNO);
1977         if (mbret == IDNO)
1978             exit(0);
1979         store_host_key(host, port, keytype, keystr);
1980     }
1981 }
1982
1983 /*
1984  * Ask whether to wipe a session log file before writing to it.
1985  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
1986  */
1987 int askappend(char *filename) {
1988     static const char mbtitle[] = "PuTTY Log to File";
1989     static const char msgtemplate[] =
1990         "The session log file \"%.*s\" already exists.\n"
1991         "You can overwrite it with a new session log,\n"
1992         "append your session log to the end of it,\n"
1993         "or disable session logging for this session.\n"
1994         "Hit Yes to wipe the file, No to append to it,\n"
1995         "or Cancel to disable logging.";
1996     char message[sizeof(msgtemplate) + FILENAME_MAX];
1997     int mbret;
1998     sprintf(message, msgtemplate, FILENAME_MAX, filename);
1999
2000     mbret = MessageBox(NULL, message, mbtitle,
2001                         MB_ICONQUESTION | MB_YESNOCANCEL);
2002     if (mbret == IDYES)
2003         return 2;
2004     else if (mbret == IDNO)
2005         return 1;
2006     else
2007         return 0;
2008 }