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