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