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