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