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