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