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