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