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