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