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