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