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