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