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