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