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