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