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