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