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