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