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