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