]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windlg.c
Continue writing documentation. Looks like a long job :-(
[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             multiedit(&cp,
848                       "Window &title:", IDC_WINTITLE,
849                       IDC_WINEDIT, 100, NULL);
850             checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
851             endbox(&cp);
852
853             treeview_insert(&tvfaff, 1, "Appearance");
854         }
855
856         /* The Translation panel. Accelerators used: [acgo] xbepnkis */
857         {
858             struct ctlpos cp;
859             ctlposinit(&cp, hwnd, 80, 3, 13);
860             bartitle(&cp, "Options controlling character set translation",
861                      IDC_TITLE_TRANSLATION);
862             beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
863                      IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
864             radiobig(&cp,
865                      "Handling of line drawing characters:", IDC_VTSTATIC,
866                      "Font has &XWindows encoding", IDC_VTXWINDOWS,
867                      "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
868                      "Use font in O&EM mode only", IDC_VTOEMONLY,
869                      "&Poor man's line drawing (""+"", ""-"" and ""|"")",
870                      IDC_VTPOORMAN, NULL);
871             endbox(&cp);
872             beginbox(&cp, "Enable character set translation on received data",
873                      IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
874             radiobig(&cp,
875                      "Character set translation:", IDC_XLATSTATIC,
876                      "&None", IDC_NOXLAT,
877                      "&KOI8 / Win-1251", IDC_KOI8WIN1251,
878                      "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
879                      "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
880             endbox(&cp);
881             beginbox(&cp, "Enable character set translation on input data",
882                      IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
883             checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
884                      IDC_CAPSLOCKCYR);
885             endbox(&cp);
886
887             treeview_insert(&tvfaff, 1, "Translation");
888         }
889
890         /* The Selection panel. Accelerators used: [acgo] wxst */
891         {
892             struct ctlpos cp;
893             ctlposinit(&cp, hwnd, 80, 3, 13);
894             bartitle(&cp, "Options controlling copy and paste",
895                      IDC_TITLE_SELECTION);
896             beginbox(&cp, "Control which mouse button does which thing",
897                      IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
898             radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
899                      "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
900                      "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
901                      NULL);
902             endbox(&cp);
903             beginbox(&cp, "Control the select-one-word-at-a-time mode",
904                      IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
905             charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
906                       "&Set", IDC_CCSET, IDC_CCEDIT,
907                       "&to class", IDC_CCSTATIC2);
908             endbox(&cp);
909
910             treeview_insert(&tvfaff, 1, "Selection");
911         }
912
913         /* The Colours panel. Accelerators used: [acgo] blum */
914         {
915             struct ctlpos cp;
916             ctlposinit(&cp, hwnd, 80, 3, 13);
917             bartitle(&cp, "Options controlling use of colours",
918                      IDC_TITLE_COLOURS);
919             beginbox(&cp, "General options for colour usage",
920                      IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
921             checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
922             checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
923             endbox(&cp);
924             beginbox(&cp, "Adjust the precise colours PuTTY displays",
925                      IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
926             colouredit(&cp, "Select a colo&ur and then click to modify it:",
927                        IDC_COLOURSTATIC, IDC_COLOURLIST,
928                        "&Modify...", IDC_CHANGE,
929                        "Red:", IDC_RSTATIC, IDC_RVALUE,
930                        "Green:", IDC_GSTATIC, IDC_GVALUE,
931                        "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
932             endbox(&cp);
933
934             treeview_insert(&tvfaff, 1, "Colours");
935         }
936
937         /* The Connection panel. Accelerators used: [acgo] tuk */
938         {
939             struct ctlpos cp;
940             ctlposinit(&cp, hwnd, 80, 3, 13);
941             bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
942             if (dlgtype == 0) {
943                 beginbox(&cp, "Data to send to the server",
944                          IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
945                 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
946                 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
947                 endbox(&cp);
948             }
949             beginbox(&cp, "Sending of null packets to keep session active",
950                      IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
951             staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
952                        IDC_PINGSTATIC, IDC_PINGEDIT, 25);
953             endbox(&cp);
954
955             treeview_insert(&tvfaff, 0, "Connection");
956         }
957
958         /* The Telnet panel. Accelerators used: [acgo] svldrbf */
959         {
960             struct ctlpos cp;
961             ctlposinit(&cp, hwnd, 80, 3, 13);
962             if (dlgtype == 0) {
963                 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
964                 beginbox(&cp, "Data to send to the server",
965                          IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
966                 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
967                 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
968                           "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
969                           "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
970                           IDC_ENVLIST,
971                           "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
972                 endbox(&cp);
973                 beginbox(&cp, "Telnet protocol adjustments",
974                          IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
975                 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
976                           "&BSD (commonplace)", IDC_EMBSD,
977                           "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
978                 endbox(&cp);
979
980                 treeview_insert(&tvfaff, 1, "Telnet");
981             }
982         }
983
984         /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
985         if (backends[2].backend != NULL) {
986             struct ctlpos cp;
987             ctlposinit(&cp, hwnd, 80, 3, 13);
988             if (dlgtype == 0) {
989                 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
990                 beginbox(&cp, "Data to send to the server",
991                          IDC_BOX_SSH1, IDC_BOXT_SSH1);
992                 multiedit(&cp,
993                           "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
994                           NULL);
995                 endbox(&cp);
996                 beginbox(&cp, "Authentication options",
997                          IDC_BOX_SSH2, IDC_BOXT_SSH2);
998                 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
999                          IDC_AUTHTIS);
1000                 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1001                 editbutton(&cp, "Private &key file for authentication:",
1002                            IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1003                 endbox(&cp);
1004                 beginbox(&cp, "Protocol options",
1005                          IDC_BOX_SSH3, IDC_BOXT_SSH3);
1006                 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1007                 checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
1008                 radioline(&cp, "Preferred SSH protocol version:",
1009                           IDC_SSHPROTSTATIC, 2,
1010                           "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1011                 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1012                           "&3DES", IDC_CIPHER3DES,
1013                           "&Blowfish", IDC_CIPHERBLOWF,
1014                           "&DES", IDC_CIPHERDES, NULL);
1015                 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1016                          IDC_BUGGYMAC);
1017                 endbox(&cp);
1018
1019                 treeview_insert(&tvfaff, 1, "SSH");
1020             }
1021         }
1022
1023         init_dlg_ctrls(hwnd);
1024         for (i = 0; i < nsessions; i++)
1025             SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1026                                 0, (LPARAM) (sessions[i]));
1027
1028         /*
1029          * Hide all the controls to start with.
1030          */
1031         hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1032
1033         /*
1034          * Put the treeview selection on to the Session panel. This
1035          * should also cause unhiding of the relevant controls.
1036          */
1037         TreeView_SelectItem(treeview, hsession);
1038
1039         /*
1040          * Set focus into the first available control.
1041          */
1042         {
1043             HWND ctl;
1044             ctl = GetDlgItem(hwnd, IDC_HOST);
1045             if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1046             SetFocus(ctl);
1047         }
1048
1049         SetWindowLong(hwnd, GWL_USERDATA, 1);
1050         return 0;
1051       case WM_LBUTTONUP:
1052         /*
1053          * Button release should trigger WM_OK if there was a
1054          * previous double click on the session list.
1055          */
1056         ReleaseCapture();
1057         if (readytogo)
1058             SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1059         break;
1060       case WM_NOTIFY:
1061         if (LOWORD(wParam) == IDCX_TREEVIEW &&
1062             ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1063             HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1064             TVITEM item;
1065             char buffer[64];
1066             item.hItem = i;
1067             item.pszText = buffer;
1068             item.cchTextMax = sizeof(buffer);
1069             item.mask = TVIF_TEXT;
1070             TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1071             hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1072             if (!strcmp(buffer, "Session"))
1073                 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1074             if (!strcmp(buffer, "Keyboard"))
1075                 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1076             if (!strcmp(buffer, "Terminal"))
1077                 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1078             if (!strcmp(buffer, "Window"))
1079                 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1080             if (!strcmp(buffer, "Appearance"))
1081                 hide(hwnd, FALSE, appearancepanelstart, appearancepanelend);
1082             if (!strcmp(buffer, "Connection"))
1083                 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1084             if (!strcmp(buffer, "Telnet"))
1085                 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1086             if (!strcmp(buffer, "SSH"))
1087                 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1088             if (!strcmp(buffer, "Selection"))
1089                 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1090             if (!strcmp(buffer, "Colours"))
1091                 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1092             if (!strcmp(buffer, "Translation"))
1093                 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1094
1095             SetFocus (((LPNMHDR)lParam)->hwndFrom);   /* ensure focus stays */
1096             return 0;
1097         }
1098         break;
1099       case WM_COMMAND:
1100         /*
1101          * Only process WM_COMMAND once the dialog is fully formed.
1102          */
1103         if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1104           case IDOK:
1105             if (*cfg.host)
1106                 EndDialog (hwnd, 1);
1107             else
1108                 MessageBeep (0);
1109             return 0;
1110           case IDCANCEL:
1111             EndDialog (hwnd, 0);
1112             return 0;
1113           case IDC_PROTTELNET:
1114           case IDC_PROTSSH:
1115           case IDC_PROTRAW:
1116             if (HIWORD(wParam) == BN_CLICKED ||
1117                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1118                 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1119                 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1120                 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1121                 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1122                     (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1123                     cfg.port = i ? 22 : 23;
1124                     SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1125                 }
1126             }
1127             break;
1128           case IDC_HOST:
1129             if (HIWORD(wParam) == EN_CHANGE)
1130                 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1131                                 sizeof(cfg.host)-1);
1132             break;
1133           case IDC_PORT:
1134             if (HIWORD(wParam) == EN_CHANGE) {
1135                 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1136                 if (isdigit(portname[0]))
1137                     MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1138                 else {
1139                     service = getservbyname(portname, NULL);
1140                     if (service) cfg.port = ntohs(service->s_port);
1141                     else cfg.port = 0;
1142                 }
1143             }
1144             break;
1145           case IDC_SESSEDIT:
1146             if (HIWORD(wParam) == EN_CHANGE) {
1147                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1148                                     (WPARAM) -1, 0);
1149                 GetDlgItemText (hwnd, IDC_SESSEDIT,
1150                                 savedsession, sizeof(savedsession)-1);
1151                 savedsession[sizeof(savedsession)-1] = '\0';
1152             }
1153             break;
1154           case IDC_SESSSAVE:
1155             if (HIWORD(wParam) == BN_CLICKED ||
1156                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1157                 /*
1158                  * Save a session
1159                  */
1160                 char str[2048];
1161                 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1162                 if (!*str) {
1163                     int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1164                                                 LB_GETCURSEL, 0, 0);
1165                     if (n == LB_ERR) {
1166                         MessageBeep(0);
1167                         break;
1168                     }
1169                     strcpy (str, sessions[n]);
1170                 }
1171                 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1172                 get_sesslist (FALSE);
1173                 get_sesslist (TRUE);
1174                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1175                                     0, 0);
1176                 for (i = 0; i < nsessions; i++)
1177                     SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1178                                         0, (LPARAM) (sessions[i]));
1179                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1180                                     (WPARAM) -1, 0);
1181             }
1182             break;
1183           case IDC_SESSLIST:
1184           case IDC_SESSLOAD:
1185             if (LOWORD(wParam) == IDC_SESSLOAD &&
1186                 HIWORD(wParam) != BN_CLICKED &&
1187                 HIWORD(wParam) != BN_DOUBLECLICKED)
1188                 break;
1189             if (LOWORD(wParam) == IDC_SESSLIST &&
1190                 HIWORD(wParam) != LBN_DBLCLK)
1191                 break;
1192             {
1193                 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1194                                             LB_GETCURSEL, 0, 0);
1195                 int isdef;
1196                 if (n == LB_ERR) {
1197                     MessageBeep(0);
1198                     break;
1199                 }
1200                 isdef = !strcmp(sessions[n], "Default Settings");
1201                 load_settings (sessions[n], !isdef, &cfg);
1202                 init_dlg_ctrls(hwnd);
1203                 if (!isdef)
1204                     SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1205                 else
1206                     SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1207             }
1208             if (LOWORD(wParam) == IDC_SESSLIST) {
1209                 /*
1210                  * A double-click on a saved session should
1211                  * actually start the session, not just load it.
1212                  * Unless it's Default Settings or some other
1213                  * host-less set of saved settings.
1214                  */
1215                 if (*cfg.host) {
1216                     readytogo = TRUE;
1217                     SetCapture(hwnd);
1218                 }
1219             }
1220             break;
1221           case IDC_SESSDEL:
1222             if (HIWORD(wParam) == BN_CLICKED ||
1223                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1224                 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1225                                             LB_GETCURSEL, 0, 0);
1226                 if (n == LB_ERR || n == 0) {
1227                     MessageBeep(0);
1228                     break;
1229                 }
1230                 del_settings(sessions[n]);
1231                 get_sesslist (FALSE);
1232                 get_sesslist (TRUE);
1233                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1234                                     0, 0);
1235                 for (i = 0; i < nsessions; i++)
1236                     SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1237                                         0, (LPARAM) (sessions[i]));
1238                 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1239                                     (WPARAM) -1, 0);
1240             }
1241           case IDC_PINGEDIT:
1242             if (HIWORD(wParam) == EN_CHANGE)
1243                 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1244             break;
1245           case IDC_DEL008:
1246           case IDC_DEL127:
1247             if (HIWORD(wParam) == BN_CLICKED ||
1248                 HIWORD(wParam) == BN_DOUBLECLICKED)
1249                 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1250             break;
1251           case IDC_HOMETILDE:
1252           case IDC_HOMERXVT:
1253             if (HIWORD(wParam) == BN_CLICKED ||
1254                 HIWORD(wParam) == BN_DOUBLECLICKED)
1255                 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1256             break;
1257           case IDC_FUNCXTERM:
1258             if (HIWORD(wParam) == BN_CLICKED ||
1259                 HIWORD(wParam) == BN_DOUBLECLICKED)
1260                 cfg.funky_type = 2;
1261             break;
1262           case IDC_FUNCVT400:
1263             if (HIWORD(wParam) == BN_CLICKED ||
1264                 HIWORD(wParam) == BN_DOUBLECLICKED)
1265                 cfg.funky_type = 3;
1266             break;
1267           case IDC_FUNCTILDE:
1268           case IDC_FUNCLINUX:
1269             if (HIWORD(wParam) == BN_CLICKED ||
1270                 HIWORD(wParam) == BN_DOUBLECLICKED)
1271                 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1272             break;
1273           case IDC_KPNORMAL:
1274           case IDC_KPAPPLIC:
1275             if (HIWORD(wParam) == BN_CLICKED ||
1276                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1277                 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1278                 cfg.nethack_keypad = FALSE;
1279             }
1280             break;
1281           case IDC_KPNH:
1282             if (HIWORD(wParam) == BN_CLICKED ||
1283                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1284                 cfg.app_keypad = FALSE;
1285                 cfg.nethack_keypad = TRUE;
1286             }
1287             break;
1288           case IDC_CURNORMAL:
1289           case IDC_CURAPPLIC:
1290             if (HIWORD(wParam) == BN_CLICKED ||
1291                 HIWORD(wParam) == BN_DOUBLECLICKED)
1292                 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1293             break;
1294           case IDC_NOAPPLICC:
1295             if (HIWORD(wParam) == BN_CLICKED ||
1296                 HIWORD(wParam) == BN_DOUBLECLICKED)
1297                 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1298             break;
1299           case IDC_NOAPPLICK:
1300             if (HIWORD(wParam) == BN_CLICKED ||
1301                 HIWORD(wParam) == BN_DOUBLECLICKED)
1302                 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1303             break;
1304           case IDC_ALTF4:
1305             if (HIWORD(wParam) == BN_CLICKED ||
1306                 HIWORD(wParam) == BN_DOUBLECLICKED)
1307                 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1308             break;
1309           case IDC_ALTSPACE:
1310             if (HIWORD(wParam) == BN_CLICKED ||
1311                 HIWORD(wParam) == BN_DOUBLECLICKED)
1312                 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1313             break;
1314           case IDC_ALTONLY:
1315             if (HIWORD(wParam) == BN_CLICKED ||
1316                 HIWORD(wParam) == BN_DOUBLECLICKED)
1317                 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1318             break;
1319           case IDC_LDISCTERM:
1320             if (HIWORD(wParam) == BN_CLICKED ||
1321                 HIWORD(wParam) == BN_DOUBLECLICKED)
1322                 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1323             break;
1324           case IDC_ALWAYSONTOP:
1325             if (HIWORD(wParam) == BN_CLICKED ||
1326                 HIWORD(wParam) == BN_DOUBLECLICKED)
1327                 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1328             break;
1329           case IDC_SCROLLKEY:
1330             if (HIWORD(wParam) == BN_CLICKED ||
1331                 HIWORD(wParam) == BN_DOUBLECLICKED)
1332                 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1333             break;
1334           case IDC_SCROLLDISP:
1335             if (HIWORD(wParam) == BN_CLICKED ||
1336                 HIWORD(wParam) == BN_DOUBLECLICKED)
1337                 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1338             break;
1339           case IDC_COMPOSEKEY:
1340             if (HIWORD(wParam) == BN_CLICKED ||
1341                 HIWORD(wParam) == BN_DOUBLECLICKED)
1342                 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1343             break;
1344           case IDC_WRAPMODE:
1345             if (HIWORD(wParam) == BN_CLICKED ||
1346                 HIWORD(wParam) == BN_DOUBLECLICKED)
1347                 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1348             break;
1349           case IDC_DECOM:
1350             if (HIWORD(wParam) == BN_CLICKED ||
1351                 HIWORD(wParam) == BN_DOUBLECLICKED)
1352                 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1353             break;
1354           case IDC_LFHASCR:
1355             if (HIWORD(wParam) == BN_CLICKED ||
1356                 HIWORD(wParam) == BN_DOUBLECLICKED)
1357                 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1358             break;
1359           case IDC_ROWSEDIT:
1360             if (HIWORD(wParam) == EN_CHANGE)
1361                 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1362             break;
1363           case IDC_COLSEDIT:
1364             if (HIWORD(wParam) == EN_CHANGE)
1365                 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1366             break;
1367           case IDC_SAVEEDIT:
1368             if (HIWORD(wParam) == EN_CHANGE)
1369                 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1370             break;
1371           case IDC_CHOOSEFONT:
1372             lf.lfHeight = cfg.fontheight;
1373             lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1374             lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1375             lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1376             lf.lfCharSet = cfg.fontcharset;
1377             lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1378             lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1379             lf.lfQuality = DEFAULT_QUALITY;
1380             lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1381             strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1382             lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1383
1384             cf.lStructSize = sizeof(cf);
1385             cf.hwndOwner = hwnd;
1386             cf.lpLogFont = &lf;
1387             cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1388                 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1389
1390             if (ChooseFont (&cf)) {
1391                 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1392                 cfg.font[sizeof(cfg.font)-1] = '\0';
1393                 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1394                 cfg.fontcharset = lf.lfCharSet;
1395                 cfg.fontheight = lf.lfHeight;
1396                 fmtfont (fontstatic);
1397                 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1398             }
1399             break;
1400           case IDC_BEEP:
1401             if (HIWORD(wParam) == BN_CLICKED ||
1402                 HIWORD(wParam) == BN_DOUBLECLICKED)
1403                 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1404             break;
1405           case IDC_BLINKTEXT:
1406             if (HIWORD(wParam) == BN_CLICKED ||
1407                 HIWORD(wParam) == BN_DOUBLECLICKED)
1408                 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1409             break;
1410           case IDC_BCE:
1411             if (HIWORD(wParam) == BN_CLICKED ||
1412                 HIWORD(wParam) == BN_DOUBLECLICKED)
1413                 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1414             break;
1415           case IDC_WINNAME:
1416             if (HIWORD(wParam) == BN_CLICKED ||
1417                 HIWORD(wParam) == BN_DOUBLECLICKED)
1418                 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1419             break;
1420           case IDC_BLINKCUR:
1421             if (HIWORD(wParam) == BN_CLICKED ||
1422                 HIWORD(wParam) == BN_DOUBLECLICKED)
1423                 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1424             break;
1425           case IDC_SCROLLBAR:
1426             if (HIWORD(wParam) == BN_CLICKED ||
1427                 HIWORD(wParam) == BN_DOUBLECLICKED)
1428                 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1429             break;
1430           case IDC_LOCKSIZE:
1431              if (HIWORD(wParam) == BN_CLICKED ||
1432                  HIWORD(wParam) == BN_DOUBLECLICKED)
1433                 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1434             break;
1435           case IDC_WINEDIT:
1436             if (HIWORD(wParam) == EN_CHANGE)
1437                 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1438                                 sizeof(cfg.wintitle)-1);
1439             break;
1440           case IDC_CLOSEEXIT:
1441             if (HIWORD(wParam) == BN_CLICKED ||
1442                 HIWORD(wParam) == BN_DOUBLECLICKED)
1443                 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1444             break;
1445           case IDC_CLOSEWARN:
1446             if (HIWORD(wParam) == BN_CLICKED ||
1447                 HIWORD(wParam) == BN_DOUBLECLICKED)
1448                 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1449             break;
1450           case IDC_TTEDIT:
1451             if (HIWORD(wParam) == EN_CHANGE)
1452             GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1453                             sizeof(cfg.termtype)-1);
1454             break;
1455           case IDC_LGFEDIT:
1456             if (HIWORD(wParam) == EN_CHANGE)
1457             GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1458                             sizeof(cfg.logfilename)-1);
1459             break;
1460           case IDC_LGFBUTTON:
1461             memset(&of, 0, sizeof(of));
1462 #ifdef OPENFILENAME_SIZE_VERSION_400
1463             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1464 #else
1465             of.lStructSize = sizeof(of);
1466 #endif
1467             of.hwndOwner = hwnd;
1468             of.lpstrFilter = "All Files\0*\0\0\0";
1469             of.lpstrCustomFilter = NULL;
1470             of.nFilterIndex = 1;
1471             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1472             of.nMaxFile = sizeof(filename);
1473             of.lpstrFileTitle = NULL;
1474             of.lpstrInitialDir = NULL;
1475             of.lpstrTitle = "Select session log file";
1476             of.Flags = 0;
1477             if (GetSaveFileName(&of)) {
1478                 strcpy(cfg.keyfile, filename);
1479                 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
1480             }
1481             break;
1482           case IDC_LSTATOFF:
1483           case IDC_LSTATASCII:
1484           case IDC_LSTATRAW:
1485             if (HIWORD(wParam) == BN_CLICKED ||
1486                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1487                 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1488                 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1489                 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1490             }
1491             break;
1492           case IDC_TSEDIT:
1493             if (HIWORD(wParam) == EN_CHANGE)
1494                 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1495                                 sizeof(cfg.termspeed)-1);
1496             break;
1497           case IDC_LOGEDIT:
1498             if (HIWORD(wParam) == EN_CHANGE)
1499                 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1500                                 sizeof(cfg.username)-1);
1501             break;
1502           case IDC_EMBSD:
1503           case IDC_EMRFC:
1504             cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1505             break;
1506           case IDC_ENVADD:
1507             if (HIWORD(wParam) == BN_CLICKED ||
1508                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1509               char str[sizeof(cfg.environmt)];
1510                 char *p;
1511                 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1512                 if (!*str) {
1513                     MessageBeep(0);
1514                     break;
1515                 }
1516                 p = str + strlen(str);
1517                 *p++ = '\t';
1518                 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1519                 if (!*p) {
1520                     MessageBeep(0);
1521                     break;
1522                 }
1523               p = cfg.environmt;
1524                 while (*p) {
1525                     while (*p) p++;
1526                     p++;
1527                 }
1528               if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1529                     strcpy (p, str);
1530                     p[strlen(str)+1] = '\0';
1531                     SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1532                                         0, (LPARAM)str);
1533                     SetDlgItemText (hwnd, IDC_VAREDIT, "");
1534                     SetDlgItemText (hwnd, IDC_VALEDIT, "");
1535                 } else {
1536                     MessageBox(hwnd, "Environment too big", "PuTTY Error",
1537                                MB_OK | MB_ICONERROR);
1538                 }
1539             }
1540             break;
1541           case IDC_ENVREMOVE:
1542             if (HIWORD(wParam) != BN_CLICKED &&
1543                 HIWORD(wParam) != BN_DOUBLECLICKED)
1544                 break;
1545             i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1546             if (i == LB_ERR)
1547                 MessageBeep (0);
1548             else {
1549                 char *p, *q;
1550
1551                 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1552                                     i, 0);
1553               p = cfg.environmt;
1554                 while (i > 0) {
1555                     if (!*p)
1556                         goto disaster;
1557                     while (*p) p++;
1558                     p++;
1559                     i--;
1560                 }
1561                 q = p;
1562                 if (!*p)
1563                     goto disaster;
1564                 while (*p) p++;
1565                 p++;
1566                 while (*p) {
1567                     while (*p)
1568                         *q++ = *p++;
1569                     *q++ = *p++;
1570                 }
1571                 *q = '\0';
1572                 disaster:;
1573             }
1574             break;
1575           case IDC_NOPTY:
1576             if (HIWORD(wParam) == BN_CLICKED ||
1577                 HIWORD(wParam) == BN_DOUBLECLICKED)
1578                 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1579             break;
1580           case IDC_COMPRESS:
1581             if (HIWORD(wParam) == BN_CLICKED ||
1582                 HIWORD(wParam) == BN_DOUBLECLICKED)
1583                 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1584             break;
1585           case IDC_BUGGYMAC:
1586             if (HIWORD(wParam) == BN_CLICKED ||
1587                 HIWORD(wParam) == BN_DOUBLECLICKED)
1588                 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1589             break;
1590           case IDC_AGENTFWD:
1591             if (HIWORD(wParam) == BN_CLICKED ||
1592                 HIWORD(wParam) == BN_DOUBLECLICKED)
1593                 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1594             break;
1595           case IDC_CIPHER3DES:
1596           case IDC_CIPHERBLOWF:
1597           case IDC_CIPHERDES:
1598             if (HIWORD(wParam) == BN_CLICKED ||
1599                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1600                 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1601                     cfg.cipher = CIPHER_3DES;
1602                 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1603                     cfg.cipher = CIPHER_BLOWFISH;
1604                 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1605                     cfg.cipher = CIPHER_DES;
1606             }
1607             break;
1608           case IDC_SSHPROT1:
1609           case IDC_SSHPROT2:
1610             if (HIWORD(wParam) == BN_CLICKED ||
1611                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1612                 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1613                     cfg.sshprot = 1;
1614                 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1615                     cfg.sshprot = 2;
1616             }
1617             break;
1618           case IDC_AUTHTIS:
1619             if (HIWORD(wParam) == BN_CLICKED ||
1620                 HIWORD(wParam) == BN_DOUBLECLICKED)
1621                 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1622             break;
1623           case IDC_PKEDIT:
1624             if (HIWORD(wParam) == EN_CHANGE)
1625                 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1626                                 sizeof(cfg.keyfile)-1);
1627             break;
1628           case IDC_CMDEDIT:
1629             if (HIWORD(wParam) == EN_CHANGE)
1630                 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1631                                 sizeof(cfg.remote_cmd)-1);
1632             break;
1633           case IDC_PKBUTTON:
1634             memset(&of, 0, sizeof(of));
1635 #ifdef OPENFILENAME_SIZE_VERSION_400
1636             of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1637 #else
1638             of.lStructSize = sizeof(of);
1639 #endif
1640             of.hwndOwner = hwnd;
1641             of.lpstrFilter = "All Files\0*\0\0\0";
1642             of.lpstrCustomFilter = NULL;
1643             of.nFilterIndex = 1;
1644             of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1645             of.nMaxFile = sizeof(filename);
1646             of.lpstrFileTitle = NULL;
1647             of.lpstrInitialDir = NULL;
1648             of.lpstrTitle = "Select Public Key File";
1649             of.Flags = 0;
1650             if (GetOpenFileName(&of)) {
1651                 strcpy(cfg.keyfile, filename);
1652                 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1653             }
1654             break;
1655           case IDC_MBWINDOWS:
1656           case IDC_MBXTERM:
1657             cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1658             break;
1659           case IDC_CCSET:
1660             {
1661                 BOOL ok;
1662                 int i;
1663                 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1664
1665                 if (!ok)
1666                     MessageBeep (0);
1667                 else {
1668                     for (i=0; i<256; i++)
1669                         if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1670                                                 i, 0)) {
1671                             char str[100];
1672                             cfg.wordness[i] = n;
1673                             SendDlgItemMessage (hwnd, IDC_CCLIST,
1674                                                 LB_DELETESTRING, i, 0);
1675                             sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1676                                     (i>=0x21 && i != 0x7F) ? i : ' ',
1677                                     cfg.wordness[i]);
1678                             SendDlgItemMessage (hwnd, IDC_CCLIST,
1679                                                 LB_INSERTSTRING, i,
1680                                                 (LPARAM)str);
1681                         }
1682                 }
1683             }
1684             break;
1685           case IDC_BOLDCOLOUR:
1686             if (HIWORD(wParam) == BN_CLICKED ||
1687                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1688                 int n, i;
1689                 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1690                 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1691                 if (n != 12+10*cfg.bold_colour) {
1692                     for (i=n; i-- >0 ;)
1693                         SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1694                                                 LB_DELETESTRING, i, 0);
1695                     for (i=0; i<22; i++)
1696                         if (cfg.bold_colour || permcolour[i])
1697                             SendDlgItemMessage (hwnd, IDC_COLOURLIST, 
1698                                                 LB_ADDSTRING, 0,
1699                                                 (LPARAM) colours[i]);
1700                 }
1701             }
1702             break;
1703           case IDC_PALETTE:
1704             if (HIWORD(wParam) == BN_CLICKED ||
1705                 HIWORD(wParam) == BN_DOUBLECLICKED)
1706                 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1707             break;
1708           case IDC_COLOURLIST:
1709             if (HIWORD(wParam) == LBN_DBLCLK ||
1710                 HIWORD(wParam) == LBN_SELCHANGE) {
1711                 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1712                                             0, 0);
1713                 if (!cfg.bold_colour)
1714                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1715                 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1716                 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1717                 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1718             }
1719             break;
1720           case IDC_CHANGE:
1721             if (HIWORD(wParam) == BN_CLICKED ||
1722                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1723                 static CHOOSECOLOR cc;
1724                 static DWORD custom[16] = {0};   /* zero initialisers */
1725                 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1726                                             0, 0);
1727                 if (!cfg.bold_colour)
1728                     i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1729                 cc.lStructSize = sizeof(cc);
1730                 cc.hwndOwner = hwnd;
1731                 cc.hInstance = (HWND)hinst;
1732                 cc.lpCustColors = custom;
1733                 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1734                                     cfg.colours[i][2]);
1735                 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1736                 if (ChooseColor(&cc)) {
1737                     cfg.colours[i][0] =
1738                         (unsigned char) (cc.rgbResult & 0xFF);
1739                     cfg.colours[i][1] =
1740                         (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1741                     cfg.colours[i][2] =
1742                         (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1743                     SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1744                                    FALSE);
1745                     SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1746                                    FALSE);
1747                     SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1748                                    FALSE);
1749                 }
1750             }
1751             break;
1752           case IDC_NOXLAT:
1753           case IDC_KOI8WIN1251:
1754           case IDC_88592WIN1250:
1755           case IDC_88592CP852:
1756             cfg.xlat_enablekoiwin =
1757                 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1758             cfg.xlat_88592w1250 =
1759                 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1760             cfg.xlat_88592cp852 =
1761                 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1762             break;
1763           case IDC_CAPSLOCKCYR:
1764             if (HIWORD(wParam) == BN_CLICKED ||
1765                 HIWORD(wParam) == BN_DOUBLECLICKED) {
1766                 cfg.xlat_capslockcyr =
1767                     IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1768             }
1769             break;
1770           case IDC_VTXWINDOWS:
1771           case IDC_VTOEMANSI:
1772           case IDC_VTOEMONLY:
1773           case IDC_VTPOORMAN:
1774             cfg.vtmode =
1775                 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1776                  IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1777                  IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1778                  VT_POORMAN);
1779             break;
1780         }
1781         return 0;
1782       case WM_CLOSE:
1783         EndDialog (hwnd, 0);
1784         return 0;
1785
1786         /* Grrr Explorer will maximize Dialogs! */
1787       case WM_SIZE:
1788         if (wParam == SIZE_MAXIMIZED)
1789            force_normal(hwnd);
1790         return 0;
1791     }
1792     return 0;
1793 }
1794
1795 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1796                                  WPARAM wParam, LPARAM lParam) {
1797     static HWND page = NULL;
1798
1799     if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1800     }
1801     if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1802         EnableWindow(hwnd, 0);
1803         DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1804                   GetParent(hwnd), AboutProc);
1805         EnableWindow(hwnd, 1);
1806         SetActiveWindow(hwnd);
1807     }
1808     return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1809 }
1810
1811 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1812                                    WPARAM wParam, LPARAM lParam) {
1813     static HWND page;
1814     return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1815 }
1816
1817 void defuse_showwindow(void) {
1818     /*
1819      * Work around the fact that the app's first call to ShowWindow
1820      * will ignore the default in favour of the shell-provided
1821      * setting.
1822      */
1823     {
1824         HWND hwnd;
1825         hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1826                              NULL, NullDlgProc);
1827         ShowWindow(hwnd, SW_HIDE);
1828         DestroyWindow(hwnd);
1829     }
1830 }
1831
1832 int do_config (void) {
1833     int ret;
1834
1835     get_sesslist(TRUE);
1836     savedsession[0] = '\0';
1837     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1838     get_sesslist(FALSE);
1839
1840     return ret;
1841 }
1842
1843 int do_reconfig (HWND hwnd) {
1844     Config backup_cfg;
1845     int ret;
1846
1847     backup_cfg = cfg;                  /* structure copy */
1848     ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1849     if (!ret)
1850         cfg = backup_cfg;              /* structure copy */
1851
1852     return ret;
1853 }
1854
1855 void logevent (char *string) {
1856     if (nevents >= negsize) {
1857         negsize += 64;
1858         events = srealloc (events, negsize * sizeof(*events));
1859     }
1860     events[nevents] = smalloc(1+strlen(string));
1861     strcpy (events[nevents], string);
1862     nevents++;
1863     if (logbox) {
1864         int count;
1865         SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1866                             0, (LPARAM)string);
1867         count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1868         SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1869     }
1870 }
1871
1872 void showeventlog (HWND hwnd) {
1873     if (!logbox) {
1874         logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1875                                hwnd, LogProc);
1876         ShowWindow (logbox, SW_SHOWNORMAL);
1877     }
1878 }
1879
1880 void showabout (HWND hwnd) {
1881     if (!abtbox) {
1882         abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1883                                hwnd, AboutProc);
1884         ShowWindow (abtbox, SW_SHOWNORMAL);
1885     }
1886 }
1887
1888 void verify_ssh_host_key(char *host, int port, char *keytype,
1889                          char *keystr, char *fingerprint) {
1890     int ret;
1891
1892     static const char absentmsg[] =
1893         "The server's host key is not cached in the registry. You\n"
1894         "have no guarantee that the server is the computer you\n"
1895         "think it is.\n"
1896         "The server's key fingerprint is:\n"
1897         "%s\n"
1898         "If you trust this host, hit Yes to add the key to\n"
1899         "PuTTY's cache and carry on connecting.\n"
1900         "If you do not trust this host, hit No to abandon the\n"
1901         "connection.\n";
1902
1903     static const char wrongmsg[] =
1904         "WARNING - POTENTIAL SECURITY BREACH!\n"
1905         "\n"
1906         "The server's host key does not match the one PuTTY has\n"
1907         "cached in the registry. This means that either the\n"
1908         "server administrator has changed the host key, or you\n"
1909         "have actually connected to another computer pretending\n"
1910         "to be the server.\n"
1911         "The new key fingerprint is:\n"
1912         "%s\n"
1913         "If you were expecting this change and trust the new key,\n"
1914         "hit Yes to update PuTTY's cache and continue connecting.\n"
1915         "If you want to carry on connecting but without updating\n"
1916         "the cache, hit No.\n"
1917         "If you want to abandon the connection completely, hit\n"
1918         "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1919         "choice.\n";
1920
1921     static const char mbtitle[] = "PuTTY Security Alert";
1922
1923     
1924     char message[160+                  /* sensible fingerprint max size */
1925                  (sizeof(absentmsg) > sizeof(wrongmsg) ?
1926                   sizeof(absentmsg) : sizeof(wrongmsg))];
1927
1928     /*
1929      * Verify the key against the registry.
1930      */
1931     ret = verify_host_key(host, port, keytype, keystr);
1932
1933     if (ret == 0)                      /* success - key matched OK */
1934         return;
1935     if (ret == 2) {                    /* key was different */
1936         int mbret;
1937         sprintf(message, wrongmsg, fingerprint);
1938         mbret = MessageBox(NULL, message, mbtitle,
1939                            MB_ICONWARNING | MB_YESNOCANCEL);
1940         if (mbret == IDYES)
1941             store_host_key(host, port, keytype, keystr);
1942         if (mbret == IDCANCEL)
1943             exit(0);
1944     }
1945     if (ret == 1) {                    /* key was absent */
1946         int mbret;
1947         sprintf(message, absentmsg, fingerprint);
1948         mbret = MessageBox(NULL, message, mbtitle,
1949                            MB_ICONWARNING | MB_YESNO);
1950         if (mbret == IDNO)
1951             exit(0);
1952         store_host_key(host, port, keytype, keystr);
1953     }
1954 }
1955
1956 /*
1957  * Ask whether to wipe a session log file before writing to it.
1958  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
1959  */
1960 int askappend(char *filename) {
1961     static const char mbtitle[] = "PuTTY Log to File";
1962     static const char msgtemplate[] =
1963         "The session log file \"%.*s\" already exists.\n"
1964         "You can overwrite it with a new session log,\n"
1965         "append your session log to the end of it,\n"
1966         "or disable session logging for this session.\n"
1967         "Hit Yes to wipe the file, No to append to it,\n"
1968         "or Cancel to disable logging.";
1969     char message[sizeof(msgtemplate) + FILENAME_MAX];
1970     int mbret;
1971     sprintf(message, msgtemplate, FILENAME_MAX, filename);
1972
1973     mbret = MessageBox(NULL, message, mbtitle,
1974                         MB_ICONQUESTION | MB_YESNOCANCEL);
1975     if (mbret == IDYES)
1976         return 2;
1977     else if (mbret == IDNO)
1978         return 1;
1979     else
1980         return 0;
1981 }