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