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