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