Add ability to configure the initial window title
[u/mdw/putty] / windlg.c
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <commdlg.h>
4 #ifndef AUTO_WINSOCK
5 #ifdef WINSOCK_TWO
6 #include <winsock2.h>
7 #else
8 #include <winsock.h>
9 #endif
10 #endif
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #include "ssh.h"
15 #include "putty.h"
16 #include "win_res.h"
17 #include "storage.h"
18
19 #define NPANELS 9
20 #define MAIN_NPANELS 9
21 #define RECONF_NPANELS 6
22
23 static char **events = NULL;
24 static int nevents = 0, negsize = 0;
25
26 static HWND logbox = NULL, abtbox = NULL;
27
28 static void gpps(void *handle, char *name, char *def, char *val, int len) {
29 if (!read_setting_s(handle, name, val, len)) {
30 strncpy(val, def, len);
31 val[len-1] = '\0';
32 }
33 }
34
35 static void gppi(void *handle, char *name, int def, int *i) {
36 *i = read_setting_i(handle, name, def);
37 }
38
39 static HINSTANCE hinst;
40
41 static int readytogo;
42
43 static void save_settings (char *section, int do_host) {
44 int i;
45 char *p;
46 void *sesskey;
47
48 sesskey = open_settings_w(section);
49 if (!sesskey)
50 return;
51
52 write_setting_i (sesskey, "Present", 1);
53 if (do_host) {
54 write_setting_s (sesskey, "HostName", cfg.host);
55 write_setting_i (sesskey, "PortNumber", cfg.port);
56 p = "raw";
57 for (i = 0; backends[i].name != NULL; i++)
58 if (backends[i].protocol == cfg.protocol) {
59 p = backends[i].name;
60 break;
61 }
62 write_setting_s (sesskey, "Protocol", p);
63 }
64 write_setting_i (sesskey, "CloseOnExit", !!cfg.close_on_exit);
65 write_setting_i (sesskey, "WarnOnClose", !!cfg.warn_on_close);
66 write_setting_s (sesskey, "TerminalType", cfg.termtype);
67 write_setting_s (sesskey, "TerminalSpeed", cfg.termspeed);
68 {
69 char buf[2*sizeof(cfg.environmt)], *p, *q;
70 p = buf;
71 q = cfg.environmt;
72 while (*q) {
73 while (*q) {
74 int c = *q++;
75 if (c == '=' || c == ',' || c == '\\')
76 *p++ = '\\';
77 if (c == '\t')
78 c = '=';
79 *p++ = c;
80 }
81 *p++ = ',';
82 q++;
83 }
84 *p = '\0';
85 write_setting_s (sesskey, "Environment", buf);
86 }
87 write_setting_s (sesskey, "UserName", cfg.username);
88 write_setting_i (sesskey, "NoPTY", cfg.nopty);
89 write_setting_i (sesskey, "AgentFwd", cfg.agentfwd);
90 write_setting_s (sesskey, "RemoteCmd", cfg.remote_cmd);
91 write_setting_s (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
92 cfg.cipher == CIPHER_DES ? "des" : "3des");
93 write_setting_i (sesskey, "AuthTIS", cfg.try_tis_auth);
94 write_setting_i (sesskey, "SshProt", cfg.sshprot);
95 write_setting_s (sesskey, "PublicKeyFile", cfg.keyfile);
96 write_setting_i (sesskey, "RFCEnviron", cfg.rfc_environ);
97 write_setting_i (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
98 write_setting_i (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
99 write_setting_i (sesskey, "LinuxFunctionKeys", cfg.funky_type);
100 write_setting_i (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
101 write_setting_i (sesskey, "ApplicationKeypad", cfg.app_keypad);
102 write_setting_i (sesskey, "NetHackKeypad", cfg.nethack_keypad);
103 write_setting_i (sesskey, "AltF4", cfg.alt_f4);
104 write_setting_i (sesskey, "AltSpace", cfg.alt_space);
105 write_setting_i (sesskey, "LdiscTerm", cfg.ldisc_term);
106 write_setting_i (sesskey, "BlinkCur", cfg.blink_cur);
107 write_setting_i (sesskey, "Beep", cfg.beep);
108 write_setting_i (sesskey, "ScrollbackLines", cfg.savelines);
109 write_setting_i (sesskey, "DECOriginMode", cfg.dec_om);
110 write_setting_i (sesskey, "AutoWrapMode", cfg.wrap_mode);
111 write_setting_i (sesskey, "LFImpliesCR", cfg.lfhascr);
112 write_setting_i (sesskey, "WinNameAlways", cfg.win_name_always);
113 write_setting_s (sesskey, "WinTitle", cfg.wintitle);
114 write_setting_i (sesskey, "TermWidth", cfg.width);
115 write_setting_i (sesskey, "TermHeight", cfg.height);
116 write_setting_s (sesskey, "Font", cfg.font);
117 write_setting_i (sesskey, "FontIsBold", cfg.fontisbold);
118 write_setting_i (sesskey, "FontCharSet", cfg.fontcharset);
119 write_setting_i (sesskey, "FontHeight", cfg.fontheight);
120 write_setting_i (sesskey, "FontVTMode", cfg.vtmode);
121 write_setting_i (sesskey, "TryPalette", cfg.try_palette);
122 write_setting_i (sesskey, "BoldAsColour", cfg.bold_colour);
123 for (i=0; i<22; i++) {
124 char buf[20], buf2[30];
125 sprintf(buf, "Colour%d", i);
126 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
127 cfg.colours[i][1], cfg.colours[i][2]);
128 write_setting_s (sesskey, buf, buf2);
129 }
130 write_setting_i (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
131 for (i=0; i<256; i+=32) {
132 char buf[20], buf2[256];
133 int j;
134 sprintf(buf, "Wordness%d", i);
135 *buf2 = '\0';
136 for (j=i; j<i+32; j++) {
137 sprintf(buf2+strlen(buf2), "%s%d",
138 (*buf2 ? "," : ""), cfg.wordness[j]);
139 }
140 write_setting_s (sesskey, buf, buf2);
141 }
142 write_setting_i (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
143 write_setting_i (sesskey, "88592Xlat", cfg.xlat_88592w1250);
144 write_setting_i (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
145 write_setting_i (sesskey, "ScrollBar", cfg.scrollbar);
146 write_setting_i (sesskey, "ScrollOnKey", cfg.scroll_on_key);
147 write_setting_i (sesskey, "LockSize", cfg.locksize);
148 write_setting_i (sesskey, "BCE", cfg.bce);
149 write_setting_i (sesskey, "BlinkText", cfg.blinktext);
150
151 close_settings_w(sesskey);
152 }
153
154 static void load_settings (char *section, int do_host) {
155 int i;
156 char prot[10];
157 void *sesskey;
158
159 sesskey = open_settings_r(section);
160
161 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
162 gppi (sesskey, "PortNumber", default_port, &cfg.port);
163
164 gpps (sesskey, "Protocol", "default", prot, 10);
165 cfg.protocol = default_protocol;
166 for (i = 0; backends[i].name != NULL; i++)
167 if (!strcmp(prot, backends[i].name)) {
168 cfg.protocol = backends[i].protocol;
169 break;
170 }
171
172 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
173 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
174 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
175 sizeof(cfg.termtype));
176 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
177 sizeof(cfg.termspeed));
178 {
179 char buf[2*sizeof(cfg.environmt)], *p, *q;
180 gpps (sesskey, "Environment", "", buf, sizeof(buf));
181 p = buf;
182 q = cfg.environmt;
183 while (*p) {
184 while (*p && *p != ',') {
185 int c = *p++;
186 if (c == '=')
187 c = '\t';
188 if (c == '\\')
189 c = *p++;
190 *q++ = c;
191 }
192 if (*p == ',') p++;
193 *q++ = '\0';
194 }
195 *q = '\0';
196 }
197 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
198 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
199 gppi (sesskey, "AgentFwd", 0, &cfg.agentfwd);
200 gpps (sesskey, "RemoteCmd", "", cfg.remote_cmd, sizeof(cfg.remote_cmd));
201 {
202 char cipher[10];
203 gpps (sesskey, "Cipher", "3des", cipher, 10);
204 if (!strcmp(cipher, "blowfish"))
205 cfg.cipher = CIPHER_BLOWFISH;
206 else if (!strcmp(cipher, "des"))
207 cfg.cipher = CIPHER_DES;
208 else
209 cfg.cipher = CIPHER_3DES;
210 }
211 gppi (sesskey, "SshProt", 1, &cfg.sshprot);
212 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
213 gpps (sesskey, "PublicKeyFile", "", cfg.keyfile, sizeof(cfg.keyfile));
214 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
215 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
216 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
217 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type);
218 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
219 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
220 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
221 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
222 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
223 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
224 gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur);
225 gppi (sesskey, "Beep", 1, &cfg.beep);
226 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
227 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
228 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
229 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
230 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
231 gpps (sesskey, "WinTitle", "", cfg.wintitle, sizeof(cfg.wintitle));
232 gppi (sesskey, "TermWidth", 80, &cfg.width);
233 gppi (sesskey, "TermHeight", 24, &cfg.height);
234 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
235 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
236 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
237 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
238 gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
239 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
240 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
241 for (i=0; i<22; i++) {
242 static char *defaults[] = {
243 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
244 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
245 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
246 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
247 "85,255,255", "187,187,187", "255,255,255"
248 };
249 char buf[20], buf2[30];
250 int c0, c1, c2;
251 sprintf(buf, "Colour%d", i);
252 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
253 if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
254 cfg.colours[i][0] = c0;
255 cfg.colours[i][1] = c1;
256 cfg.colours[i][2] = c2;
257 }
258 }
259 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
260 for (i=0; i<256; i+=32) {
261 static char *defaults[] = {
262 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
263 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
264 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
265 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
266 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
267 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
268 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
269 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
270 };
271 char buf[20], buf2[256], *p;
272 int j;
273 sprintf(buf, "Wordness%d", i);
274 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
275 p = buf2;
276 for (j=i; j<i+32; j++) {
277 char *q = p;
278 while (*p && *p != ',') p++;
279 if (*p == ',') *p++ = '\0';
280 cfg.wordness[j] = atoi(q);
281 }
282 }
283 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
284 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
285 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
286 gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar);
287 gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key);
288 gppi (sesskey, "LockSize", 0, &cfg.locksize);
289 gppi (sesskey, "BCE", 0, &cfg.bce);
290 gppi (sesskey, "BlinkText", 0, &cfg.blinktext);
291
292 close_settings_r(sesskey);
293 }
294
295 static void force_normal(HWND hwnd)
296 {
297 static int recurse = 0;
298
299 WINDOWPLACEMENT wp;
300
301 if(recurse) return;
302 recurse = 1;
303
304 wp.length = sizeof(wp);
305 if (GetWindowPlacement(hwnd, &wp))
306 {
307 wp.showCmd = SW_SHOWNORMAL;
308 SetWindowPlacement(hwnd, &wp);
309 }
310 recurse = 0;
311 }
312
313 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
314 BOOL ok;
315 int n;
316 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
317 if (ok)
318 *result = n;
319 }
320
321 static int CALLBACK LogProc (HWND hwnd, UINT msg,
322 WPARAM wParam, LPARAM lParam) {
323 int i;
324
325 switch (msg) {
326 case WM_INITDIALOG:
327 for (i=0; i<nevents; i++)
328 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
329 0, (LPARAM)events[i]);
330 return 1;
331 /* case WM_CTLCOLORDLG: */
332 /* return (int) GetStockObject (LTGRAY_BRUSH); */
333 case WM_COMMAND:
334 switch (LOWORD(wParam)) {
335 case IDOK:
336 logbox = NULL;
337 DestroyWindow (hwnd);
338 return 0;
339 case IDN_COPY:
340 if (HIWORD(wParam) == BN_CLICKED ||
341 HIWORD(wParam) == BN_DOUBLECLICKED) {
342 int selcount;
343 int *selitems;
344 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
345 LB_GETSELCOUNT, 0, 0);
346 selitems = malloc(selcount * sizeof(int));
347 if (selitems) {
348 int count = SendDlgItemMessage(hwnd, IDN_LIST,
349 LB_GETSELITEMS,
350 selcount, (LPARAM)selitems);
351 int i;
352 int size;
353 char *clipdata;
354 static unsigned char sel_nl[] = SEL_NL;
355
356 size = 0;
357 for (i = 0; i < count; i++)
358 size += strlen(events[selitems[i]]) + sizeof(sel_nl);
359
360 clipdata = malloc(size);
361 if (clipdata) {
362 char *p = clipdata;
363 for (i = 0; i < count; i++) {
364 char *q = events[selitems[i]];
365 int qlen = strlen(q);
366 memcpy(p, q, qlen);
367 p += qlen;
368 memcpy(p, sel_nl, sizeof(sel_nl));
369 p += sizeof(sel_nl);
370 }
371 write_clip(clipdata, size);
372 term_deselect();
373 free(clipdata);
374 }
375 free(selitems);
376 }
377 }
378 return 0;
379 }
380 return 0;
381 case WM_CLOSE:
382 logbox = NULL;
383 DestroyWindow (hwnd);
384 return 0;
385 }
386 return 0;
387 }
388
389 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
390 WPARAM wParam, LPARAM lParam) {
391 switch (msg) {
392 case WM_INITDIALOG:
393 return 1;
394 case WM_COMMAND:
395 switch (LOWORD(wParam)) {
396 case IDOK:
397 EndDialog(hwnd, 1);
398 return 0;
399 }
400 return 0;
401 case WM_CLOSE:
402 EndDialog(hwnd, 1);
403 return 0;
404 }
405 return 0;
406 }
407
408 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
409 WPARAM wParam, LPARAM lParam) {
410 switch (msg) {
411 case WM_INITDIALOG:
412 SetDlgItemText (hwnd, IDA_VERSION, ver);
413 return 1;
414 /* case WM_CTLCOLORDLG: */
415 /* return (int) GetStockObject (LTGRAY_BRUSH); */
416 /* case WM_CTLCOLORSTATIC: */
417 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
418 /* return (int) GetStockObject (LTGRAY_BRUSH); */
419 case WM_COMMAND:
420 switch (LOWORD(wParam)) {
421 case IDOK:
422 abtbox = NULL;
423 DestroyWindow (hwnd);
424 return 0;
425 case IDA_LICENCE:
426 EnableWindow(hwnd, 0);
427 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
428 NULL, LicenceProc);
429 EnableWindow(hwnd, 1);
430 SetActiveWindow(hwnd);
431 return 0;
432 }
433 return 0;
434 case WM_CLOSE:
435 abtbox = NULL;
436 DestroyWindow (hwnd);
437 return 0;
438 }
439 return 0;
440 }
441
442 static int GeneralPanelProc (HWND hwnd, UINT msg,
443 WPARAM wParam, LPARAM lParam) {
444 switch (msg) {
445 case WM_INITDIALOG:
446 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
447 return 1;
448 /* case WM_CTLCOLORDLG: */
449 /* return (int) GetStockObject (LTGRAY_BRUSH); */
450 /* case WM_CTLCOLORSTATIC: */
451 /* case WM_CTLCOLORBTN: */
452 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
453 /* return (int) GetStockObject (LTGRAY_BRUSH); */
454 case WM_CLOSE:
455 DestroyWindow (hwnd);
456 return 1;
457 }
458 return 0;
459 }
460
461 static char savedsession[2048];
462
463 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
464 WPARAM wParam, LPARAM lParam) {
465 int i;
466
467 switch (msg) {
468 case WM_INITDIALOG:
469 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
470 SetDlgItemText (hwnd, IDC0_SESSEDIT, savedsession);
471 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
472 for (i = 0; i < nsessions; i++)
473 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
474 0, (LPARAM) (sessions[i]));
475 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
476 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
477 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
478 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
479 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
480 break;
481 case WM_LBUTTONUP:
482 /*
483 * Button release should trigger WM_OK if there was a
484 * previous double click on the session list.
485 */
486 ReleaseCapture();
487 if (readytogo)
488 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
489 break;
490 case WM_COMMAND:
491 switch (LOWORD(wParam)) {
492 case IDC0_PROTTELNET:
493 case IDC0_PROTSSH:
494 case IDC0_PROTRAW:
495 if (HIWORD(wParam) == BN_CLICKED ||
496 HIWORD(wParam) == BN_DOUBLECLICKED) {
497 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
498 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
499 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
500 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
501 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
502 cfg.port = i ? 22 : 23;
503 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
504 }
505 }
506 break;
507 case IDC0_HOST:
508 if (HIWORD(wParam) == EN_CHANGE)
509 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
510 sizeof(cfg.host)-1);
511 break;
512 case IDC0_PORT:
513 if (HIWORD(wParam) == EN_CHANGE)
514 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
515 break;
516 case IDC0_CLOSEEXIT:
517 if (HIWORD(wParam) == BN_CLICKED ||
518 HIWORD(wParam) == BN_DOUBLECLICKED)
519 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
520 break;
521 case IDC0_CLOSEWARN:
522 if (HIWORD(wParam) == BN_CLICKED ||
523 HIWORD(wParam) == BN_DOUBLECLICKED)
524 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
525 break;
526 case IDC0_SESSEDIT:
527 if (HIWORD(wParam) == EN_CHANGE) {
528 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
529 (WPARAM) -1, 0);
530 GetDlgItemText (hwnd, IDC0_SESSEDIT,
531 savedsession, sizeof(savedsession)-1);
532 savedsession[sizeof(savedsession)-1] = '\0';
533 }
534 break;
535 case IDC0_SESSSAVE:
536 if (HIWORD(wParam) == BN_CLICKED ||
537 HIWORD(wParam) == BN_DOUBLECLICKED) {
538 /*
539 * Save a session
540 */
541 char str[2048];
542 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
543 if (!*str) {
544 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
545 LB_GETCURSEL, 0, 0);
546 if (n == LB_ERR) {
547 MessageBeep(0);
548 break;
549 }
550 strcpy (str, sessions[n]);
551 }
552 save_settings (str, !!strcmp(str, "Default Settings"));
553 get_sesslist (FALSE);
554 get_sesslist (TRUE);
555 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
556 0, 0);
557 for (i = 0; i < nsessions; i++)
558 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
559 0, (LPARAM) (sessions[i]));
560 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
561 (WPARAM) -1, 0);
562 }
563 break;
564 case IDC0_SESSLIST:
565 case IDC0_SESSLOAD:
566 if (LOWORD(wParam) == IDC0_SESSLOAD &&
567 HIWORD(wParam) != BN_CLICKED &&
568 HIWORD(wParam) != BN_DOUBLECLICKED)
569 break;
570 if (LOWORD(wParam) == IDC0_SESSLIST &&
571 HIWORD(wParam) != LBN_DBLCLK)
572 break;
573 {
574 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
575 LB_GETCURSEL, 0, 0);
576 if (n == LB_ERR) {
577 MessageBeep(0);
578 break;
579 }
580 load_settings (sessions[n],
581 !!strcmp(sessions[n], "Default Settings"));
582 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
583 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
584 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
585 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
586 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
587 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
588 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
589 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
590 (WPARAM) -1, 0);
591 }
592 if (LOWORD(wParam) == IDC0_SESSLIST) {
593 /*
594 * A double-click on a saved session should
595 * actually start the session, not just load it.
596 * Unless it's Default Settings or some other
597 * host-less set of saved settings.
598 */
599 if (*cfg.host) {
600 readytogo = TRUE;
601 SetCapture(hwnd);
602 }
603 }
604 break;
605 case IDC0_SESSDEL:
606 if (HIWORD(wParam) == BN_CLICKED ||
607 HIWORD(wParam) == BN_DOUBLECLICKED) {
608 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
609 LB_GETCURSEL, 0, 0);
610 if (n == LB_ERR || n == 0) {
611 MessageBeep(0);
612 break;
613 }
614 del_settings(sessions[n]);
615 get_sesslist (FALSE);
616 get_sesslist (TRUE);
617 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
618 0, 0);
619 for (i = 0; i < nsessions; i++)
620 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
621 0, (LPARAM) (sessions[i]));
622 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
623 (WPARAM) -1, 0);
624 }
625 }
626 }
627 return GeneralPanelProc (hwnd, msg, wParam, lParam);
628 }
629
630 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
631 WPARAM wParam, LPARAM lParam) {
632 switch (msg) {
633 case WM_INITDIALOG:
634 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
635 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
636 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
637 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
638 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
639 cfg.funky_type ?
640 (cfg.funky_type==2 ? IDC1_FUNCXTERM
641 : IDC1_FUNCLINUX )
642 : IDC1_FUNCTILDE);
643 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
644 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
645 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
646 cfg.nethack_keypad ? IDC1_KPNH :
647 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
648 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
649 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
650 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
651 CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
652 break;
653 case WM_COMMAND:
654 if (HIWORD(wParam) == BN_CLICKED ||
655 HIWORD(wParam) == BN_DOUBLECLICKED)
656 switch (LOWORD(wParam)) {
657 case IDC1_DEL008:
658 case IDC1_DEL127:
659 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
660 break;
661 case IDC1_HOMETILDE:
662 case IDC1_HOMERXVT:
663 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
664 break;
665 case IDC1_FUNCXTERM:
666 cfg.funky_type = 2;
667 break;
668 case IDC1_FUNCTILDE:
669 case IDC1_FUNCLINUX:
670 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
671 break;
672 case IDC1_KPNORMAL:
673 case IDC1_KPAPPLIC:
674 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
675 cfg.nethack_keypad = FALSE;
676 break;
677 case IDC1_KPNH:
678 cfg.app_keypad = FALSE;
679 cfg.nethack_keypad = TRUE;
680 break;
681 case IDC1_CURNORMAL:
682 case IDC1_CURAPPLIC:
683 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
684 break;
685 case IDC1_ALTF4:
686 if (HIWORD(wParam) == BN_CLICKED ||
687 HIWORD(wParam) == BN_DOUBLECLICKED)
688 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
689 break;
690 case IDC1_ALTSPACE:
691 if (HIWORD(wParam) == BN_CLICKED ||
692 HIWORD(wParam) == BN_DOUBLECLICKED)
693 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
694 break;
695 case IDC1_LDISCTERM:
696 if (HIWORD(wParam) == BN_CLICKED ||
697 HIWORD(wParam) == BN_DOUBLECLICKED)
698 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
699 break;
700 case IDC1_SCROLLKEY:
701 if (HIWORD(wParam) == BN_CLICKED ||
702 HIWORD(wParam) == BN_DOUBLECLICKED)
703 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
704 break;
705 }
706 }
707 return GeneralPanelProc (hwnd, msg, wParam, lParam);
708 }
709
710 static void fmtfont (char *buf) {
711 sprintf (buf, "Font: %s, ", cfg.font);
712 if (cfg.fontisbold)
713 strcat(buf, "bold, ");
714 if (cfg.fontheight == 0)
715 strcat (buf, "default height");
716 else
717 sprintf (buf+strlen(buf), "%d-%s",
718 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
719 (cfg.fontheight < 0 ? "pixel" : "point"));
720 }
721
722 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
723 WPARAM wParam, LPARAM lParam) {
724 CHOOSEFONT cf;
725 LOGFONT lf;
726 char fontstatic[256];
727
728 switch (msg) {
729 case WM_INITDIALOG:
730 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
731 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
732 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
733 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
734 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
735 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
736 fmtfont (fontstatic);
737 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
738 CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
739 CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
740 CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
741 break;
742 case WM_COMMAND:
743 switch (LOWORD(wParam)) {
744 case IDC2_WRAPMODE:
745 if (HIWORD(wParam) == BN_CLICKED ||
746 HIWORD(wParam) == BN_DOUBLECLICKED)
747 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
748 break;
749 case IDC2_DECOM:
750 if (HIWORD(wParam) == BN_CLICKED ||
751 HIWORD(wParam) == BN_DOUBLECLICKED)
752 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
753 break;
754 case IDC2_LFHASCR:
755 if (HIWORD(wParam) == BN_CLICKED ||
756 HIWORD(wParam) == BN_DOUBLECLICKED)
757 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
758 break;
759 case IDC2_ROWSEDIT:
760 if (HIWORD(wParam) == EN_CHANGE)
761 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
762 break;
763 case IDC2_COLSEDIT:
764 if (HIWORD(wParam) == EN_CHANGE)
765 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
766 break;
767 case IDC2_SAVEEDIT:
768 if (HIWORD(wParam) == EN_CHANGE)
769 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
770 break;
771 case IDC2_CHOOSEFONT:
772 lf.lfHeight = cfg.fontheight;
773 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
774 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
775 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
776 lf.lfCharSet = cfg.fontcharset;
777 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
778 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
779 lf.lfQuality = DEFAULT_QUALITY;
780 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
781 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
782 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
783
784 cf.lStructSize = sizeof(cf);
785 cf.hwndOwner = hwnd;
786 cf.lpLogFont = &lf;
787 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
788 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
789
790 if (ChooseFont (&cf)) {
791 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
792 cfg.font[sizeof(cfg.font)-1] = '\0';
793 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
794 cfg.fontcharset = lf.lfCharSet;
795 cfg.fontheight = lf.lfHeight;
796 fmtfont (fontstatic);
797 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
798 }
799 break;
800 case IDC1_BEEP:
801 if (HIWORD(wParam) == BN_CLICKED ||
802 HIWORD(wParam) == BN_DOUBLECLICKED)
803 cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
804 break;
805 case IDC2_BLINKTEXT:
806 if (HIWORD(wParam) == BN_CLICKED ||
807 HIWORD(wParam) == BN_DOUBLECLICKED)
808 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
809 break;
810 case IDC2_BCE:
811 if (HIWORD(wParam) == BN_CLICKED ||
812 HIWORD(wParam) == BN_DOUBLECLICKED)
813 cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
814 break;
815 }
816 break;
817 }
818 return GeneralPanelProc (hwnd, msg, wParam, lParam);
819 }
820
821 static int CALLBACK WindowProc (HWND hwnd, UINT msg,
822 WPARAM wParam, LPARAM lParam) {
823 switch (msg) {
824 case WM_INITDIALOG:
825 SetDlgItemText (hwnd, IDCW_WINEDIT, cfg.wintitle);
826 CheckDlgButton (hwnd, IDCW_WINNAME, cfg.win_name_always);
827 CheckDlgButton (hwnd, IDCW_BLINKCUR, cfg.blink_cur);
828 CheckDlgButton (hwnd, IDCW_SCROLLBAR, cfg.scrollbar);
829 CheckDlgButton (hwnd, IDCW_LOCKSIZE, cfg.locksize);
830 break;
831 case WM_COMMAND:
832 switch (LOWORD(wParam)) {
833 case IDCW_WINNAME:
834 if (HIWORD(wParam) == BN_CLICKED ||
835 HIWORD(wParam) == BN_DOUBLECLICKED)
836 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDCW_WINNAME);
837 break;
838 case IDCW_BLINKCUR:
839 if (HIWORD(wParam) == BN_CLICKED ||
840 HIWORD(wParam) == BN_DOUBLECLICKED)
841 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDCW_BLINKCUR);
842 break;
843 case IDCW_SCROLLBAR:
844 if (HIWORD(wParam) == BN_CLICKED ||
845 HIWORD(wParam) == BN_DOUBLECLICKED)
846 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDCW_SCROLLBAR);
847 break;
848 case IDCW_LOCKSIZE:
849 if (HIWORD(wParam) == BN_CLICKED ||
850 HIWORD(wParam) == BN_DOUBLECLICKED)
851 cfg.locksize = IsDlgButtonChecked (hwnd, IDCW_LOCKSIZE);
852 break;
853 case IDCW_WINEDIT:
854 if (HIWORD(wParam) == EN_CHANGE)
855 GetDlgItemText (hwnd, IDCW_WINEDIT, cfg.wintitle,
856 sizeof(cfg.wintitle)-1);
857 break;
858 }
859 break;
860 }
861 return GeneralPanelProc (hwnd, msg, wParam, lParam);
862 }
863
864 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
865 WPARAM wParam, LPARAM lParam) {
866 int i;
867
868 switch (msg) {
869 case WM_INITDIALOG:
870 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
871 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
872 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
873 {
874 char *p = cfg.environmt;
875 while (*p) {
876 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
877 (LPARAM) p);
878 p += strlen(p)+1;
879 }
880 }
881 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
882 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
883 break;
884 case WM_COMMAND:
885 switch (LOWORD(wParam)) {
886 case IDC3_TTEDIT:
887 if (HIWORD(wParam) == EN_CHANGE)
888 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
889 sizeof(cfg.termtype)-1);
890 break;
891 case IDC3_TSEDIT:
892 if (HIWORD(wParam) == EN_CHANGE)
893 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
894 sizeof(cfg.termspeed)-1);
895 break;
896 case IDC3_LOGEDIT:
897 if (HIWORD(wParam) == EN_CHANGE)
898 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
899 sizeof(cfg.username)-1);
900 break;
901 case IDC3_EMBSD:
902 case IDC3_EMRFC:
903 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
904 break;
905 case IDC3_ENVADD:
906 if (HIWORD(wParam) == BN_CLICKED ||
907 HIWORD(wParam) == BN_DOUBLECLICKED) {
908 char str[sizeof(cfg.environmt)];
909 char *p;
910 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
911 if (!*str) {
912 MessageBeep(0);
913 break;
914 }
915 p = str + strlen(str);
916 *p++ = '\t';
917 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
918 if (!*p) {
919 MessageBeep(0);
920 break;
921 }
922 p = cfg.environmt;
923 while (*p) {
924 while (*p) p++;
925 p++;
926 }
927 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
928 strcpy (p, str);
929 p[strlen(str)+1] = '\0';
930 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
931 0, (LPARAM)str);
932 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
933 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
934 } else {
935 MessageBox(hwnd, "Environment too big", "PuTTY Error",
936 MB_OK | MB_ICONERROR);
937 }
938 }
939 break;
940 case IDC3_ENVREMOVE:
941 if (HIWORD(wParam) != BN_CLICKED &&
942 HIWORD(wParam) != BN_DOUBLECLICKED)
943 break;
944 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
945 if (i == LB_ERR)
946 MessageBeep (0);
947 else {
948 char *p, *q;
949
950 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
951 i, 0);
952 p = cfg.environmt;
953 while (i > 0) {
954 if (!*p)
955 goto disaster;
956 while (*p) p++;
957 p++;
958 i--;
959 }
960 q = p;
961 if (!*p)
962 goto disaster;
963 while (*p) p++;
964 p++;
965 while (*p) {
966 while (*p)
967 *q++ = *p++;
968 *q++ = *p++;
969 }
970 *q = '\0';
971 disaster:;
972 }
973 break;
974 }
975 break;
976 }
977 return GeneralPanelProc (hwnd, msg, wParam, lParam);
978 }
979
980 static int CALLBACK SshProc (HWND hwnd, UINT msg,
981 WPARAM wParam, LPARAM lParam) {
982 OPENFILENAME of;
983 char filename[sizeof(cfg.keyfile)];
984
985 switch (msg) {
986 case WM_INITDIALOG:
987 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
988 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
989 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
990 CheckDlgButton (hwnd, IDC3_AGENTFWD, cfg.agentfwd);
991 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
992 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
993 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
994 IDC3_CIPHER3DES);
995 CheckRadioButton (hwnd, IDC3_SSHPROT1, IDC3_SSHPROT2,
996 cfg.sshprot == 1 ? IDC3_SSHPROT1 : IDC3_SSHPROT2);
997 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
998 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
999 break;
1000 case WM_COMMAND:
1001 switch (LOWORD(wParam)) {
1002 case IDC3_TTEDIT:
1003 if (HIWORD(wParam) == EN_CHANGE)
1004 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
1005 sizeof(cfg.termtype)-1);
1006 break;
1007 case IDC3_LOGEDIT:
1008 if (HIWORD(wParam) == EN_CHANGE)
1009 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
1010 sizeof(cfg.username)-1);
1011 break;
1012 case IDC3_NOPTY:
1013 if (HIWORD(wParam) == BN_CLICKED ||
1014 HIWORD(wParam) == BN_DOUBLECLICKED)
1015 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
1016 break;
1017 case IDC3_AGENTFWD:
1018 if (HIWORD(wParam) == BN_CLICKED ||
1019 HIWORD(wParam) == BN_DOUBLECLICKED)
1020 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC3_AGENTFWD);
1021 break;
1022 case IDC3_CIPHER3DES:
1023 case IDC3_CIPHERBLOWF:
1024 case IDC3_CIPHERDES:
1025 if (HIWORD(wParam) == BN_CLICKED ||
1026 HIWORD(wParam) == BN_DOUBLECLICKED) {
1027 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
1028 cfg.cipher = CIPHER_3DES;
1029 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
1030 cfg.cipher = CIPHER_BLOWFISH;
1031 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
1032 cfg.cipher = CIPHER_DES;
1033 }
1034 break;
1035 case IDC3_SSHPROT1:
1036 case IDC3_SSHPROT2:
1037 if (HIWORD(wParam) == BN_CLICKED ||
1038 HIWORD(wParam) == BN_DOUBLECLICKED) {
1039 if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT1))
1040 cfg.sshprot = 1;
1041 else if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT2))
1042 cfg.sshprot = 2;
1043 }
1044 break;
1045 case IDC3_AUTHTIS:
1046 if (HIWORD(wParam) == BN_CLICKED ||
1047 HIWORD(wParam) == BN_DOUBLECLICKED)
1048 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
1049 break;
1050 case IDC3_PKEDIT:
1051 if (HIWORD(wParam) == EN_CHANGE)
1052 GetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile,
1053 sizeof(cfg.keyfile)-1);
1054 break;
1055 case IDC3_PKBUTTON:
1056 /*
1057 * FIXME: this crashes. Find out why.
1058 */
1059 memset(&of, 0, sizeof(of));
1060 #ifdef OPENFILENAME_SIZE_VERSION_400
1061 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1062 #else
1063 of.lStructSize = sizeof(of);
1064 #endif
1065 of.hwndOwner = hwnd;
1066 of.lpstrFilter = "All Files\0*\0\0\0";
1067 of.lpstrCustomFilter = NULL;
1068 of.nFilterIndex = 1;
1069 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1070 of.nMaxFile = sizeof(filename);
1071 of.lpstrFileTitle = NULL;
1072 of.lpstrInitialDir = NULL;
1073 of.lpstrTitle = "Select Public Key File";
1074 of.Flags = 0;
1075 if (GetOpenFileName(&of)) {
1076 strcpy(cfg.keyfile, filename);
1077 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1078 }
1079 break;
1080 }
1081 break;
1082 }
1083 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1084 }
1085
1086 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1087 WPARAM wParam, LPARAM lParam) {
1088 int i;
1089
1090 switch (msg) {
1091 case WM_INITDIALOG:
1092 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1093 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1094 {
1095 static int tabs[4] = {25, 61, 96, 128};
1096 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1097 (LPARAM) tabs);
1098 }
1099 for (i=0; i<256; i++) {
1100 char str[100];
1101 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1102 (i>=0x21 && i != 0x7F) ? i : ' ',
1103 cfg.wordness[i]);
1104 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1105 (LPARAM) str);
1106 }
1107 break;
1108 case WM_COMMAND:
1109 switch (LOWORD(wParam)) {
1110 case IDC4_MBWINDOWS:
1111 case IDC4_MBXTERM:
1112 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1113 break;
1114 case IDC4_CCSET:
1115 {
1116 BOOL ok;
1117 int i;
1118 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1119
1120 if (!ok)
1121 MessageBeep (0);
1122 else {
1123 for (i=0; i<256; i++)
1124 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1125 i, 0)) {
1126 char str[100];
1127 cfg.wordness[i] = n;
1128 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1129 LB_DELETESTRING, i, 0);
1130 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1131 (i>=0x21 && i != 0x7F) ? i : ' ',
1132 cfg.wordness[i]);
1133 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1134 LB_INSERTSTRING, i,
1135 (LPARAM)str);
1136 }
1137 }
1138 }
1139 break;
1140 }
1141 break;
1142 }
1143 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1144 }
1145
1146 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1147 WPARAM wParam, LPARAM lParam) {
1148 static const char *const colours[] = {
1149 "Default Foreground", "Default Bold Foreground",
1150 "Default Background", "Default Bold Background",
1151 "Cursor Text", "Cursor Colour",
1152 "ANSI Black", "ANSI Black Bold",
1153 "ANSI Red", "ANSI Red Bold",
1154 "ANSI Green", "ANSI Green Bold",
1155 "ANSI Yellow", "ANSI Yellow Bold",
1156 "ANSI Blue", "ANSI Blue Bold",
1157 "ANSI Magenta", "ANSI Magenta Bold",
1158 "ANSI Cyan", "ANSI Cyan Bold",
1159 "ANSI White", "ANSI White Bold"
1160 };
1161 static const int permanent[] = {
1162 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1163 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1164 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1165 };
1166 switch (msg) {
1167 case WM_INITDIALOG:
1168 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1169 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1170 {
1171 int i;
1172 for (i=0; i<22; i++)
1173 if (cfg.bold_colour || permanent[i])
1174 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1175 (LPARAM) colours[i]);
1176 }
1177 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1178 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1179 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1180 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1181 break;
1182 case WM_COMMAND:
1183 switch (LOWORD(wParam)) {
1184 case IDC5_BOLDCOLOUR:
1185 if (HIWORD(wParam) == BN_CLICKED ||
1186 HIWORD(wParam) == BN_DOUBLECLICKED) {
1187 int n, i;
1188 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1189 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1190 if (cfg.bold_colour && n!=22) {
1191 for (i=0; i<22; i++)
1192 if (!permanent[i])
1193 SendDlgItemMessage (hwnd, IDC5_LIST,
1194 LB_INSERTSTRING, i,
1195 (LPARAM) colours[i]);
1196 } else if (!cfg.bold_colour && n!=12) {
1197 for (i=22; i-- ;)
1198 if (!permanent[i])
1199 SendDlgItemMessage (hwnd, IDC5_LIST,
1200 LB_DELETESTRING, i, 0);
1201 }
1202 }
1203 break;
1204 case IDC5_PALETTE:
1205 if (HIWORD(wParam) == BN_CLICKED ||
1206 HIWORD(wParam) == BN_DOUBLECLICKED)
1207 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1208 break;
1209 case IDC5_LIST:
1210 if (HIWORD(wParam) == LBN_DBLCLK ||
1211 HIWORD(wParam) == LBN_SELCHANGE) {
1212 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1213 0, 0);
1214 if (!cfg.bold_colour)
1215 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1216 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1217 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1218 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1219 }
1220 break;
1221 case IDC5_CHANGE:
1222 if (HIWORD(wParam) == BN_CLICKED ||
1223 HIWORD(wParam) == BN_DOUBLECLICKED) {
1224 static CHOOSECOLOR cc;
1225 static DWORD custom[16] = {0}; /* zero initialisers */
1226 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1227 0, 0);
1228 if (!cfg.bold_colour)
1229 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1230 cc.lStructSize = sizeof(cc);
1231 cc.hwndOwner = hwnd;
1232 cc.hInstance = (HWND)hinst;
1233 cc.lpCustColors = custom;
1234 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1235 cfg.colours[i][2]);
1236 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1237 if (ChooseColor(&cc)) {
1238 cfg.colours[i][0] =
1239 (unsigned char) (cc.rgbResult & 0xFF);
1240 cfg.colours[i][1] =
1241 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1242 cfg.colours[i][2] =
1243 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1244 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1245 FALSE);
1246 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1247 FALSE);
1248 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1249 FALSE);
1250 }
1251 }
1252 break;
1253 }
1254 break;
1255 }
1256 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1257 }
1258
1259 static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
1260 WPARAM wParam, LPARAM lParam) {
1261 switch (msg) {
1262 case WM_INITDIALOG:
1263 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1264 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1265 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1266 IDC6_NOXLAT);
1267 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1268 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
1269 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
1270 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
1271 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
1272 IDC2_VTPOORMAN);
1273 case WM_COMMAND:
1274 switch (LOWORD(wParam)) {
1275 case IDC6_NOXLAT:
1276 case IDC6_KOI8WIN1251:
1277 case IDC6_88592WIN1250:
1278 cfg.xlat_enablekoiwin =
1279 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1280 cfg.xlat_88592w1250 =
1281 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1282 break;
1283 case IDC6_CAPSLOCKCYR:
1284 if (HIWORD(wParam) == BN_CLICKED ||
1285 HIWORD(wParam) == BN_DOUBLECLICKED) {
1286 cfg.xlat_capslockcyr =
1287 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1288 }
1289 break;
1290 case IDC2_VTXWINDOWS:
1291 case IDC2_VTOEMANSI:
1292 case IDC2_VTOEMONLY:
1293 case IDC2_VTPOORMAN:
1294 cfg.vtmode =
1295 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
1296 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
1297 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
1298 VT_POORMAN);
1299 break;
1300 }
1301 }
1302 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1303 }
1304
1305 static DLGPROC panelproc[NPANELS] = {
1306 ConnectionProc, KeyboardProc, TerminalProc, WindowProc,
1307 TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
1308 };
1309 static char *panelids[NPANELS] = {
1310 MAKEINTRESOURCE(IDD_PANEL0),
1311 MAKEINTRESOURCE(IDD_PANEL1),
1312 MAKEINTRESOURCE(IDD_PANEL2),
1313 MAKEINTRESOURCE(IDD_PANELW),
1314 MAKEINTRESOURCE(IDD_PANEL3),
1315 MAKEINTRESOURCE(IDD_PANEL35),
1316 MAKEINTRESOURCE(IDD_PANEL4),
1317 MAKEINTRESOURCE(IDD_PANEL5),
1318 MAKEINTRESOURCE(IDD_PANEL6)
1319 };
1320
1321 static char *names[NPANELS] = {
1322 "Connection", "Keyboard", "Terminal", "Window", "Telnet",
1323 "SSH", "Selection", "Colours", "Translation"
1324 };
1325
1326 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
1327 static int reconfp[RECONF_NPANELS] = { 1, 2, 3, 6, 7, 8};
1328
1329 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1330 WPARAM wParam, LPARAM lParam,
1331 int npanels, int *panelnums, HWND *page) {
1332 HWND hw;
1333
1334 switch (msg) {
1335 case WM_INITDIALOG:
1336 { /* centre the window */
1337 RECT rs, rd;
1338
1339 hw = GetDesktopWindow();
1340 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1341 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1342 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1343 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1344 }
1345 *page = NULL;
1346 { /* initialise the tab control */
1347 TC_ITEMHEADER tab;
1348 int i;
1349
1350 hw = GetDlgItem (hwnd, IDC_TAB);
1351 for (i=0; i<npanels; i++) {
1352 tab.mask = TCIF_TEXT;
1353 tab.pszText = names[panelnums[i]];
1354 TabCtrl_InsertItem (hw, i, &tab);
1355 }
1356 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1357 hwnd, panelproc[panelnums[0]]);*/
1358 *page = CreateDialog (hinst, panelids[panelnums[0]],
1359 hwnd, panelproc[panelnums[0]]);
1360 SetWindowLong (*page, GWL_EXSTYLE,
1361 GetWindowLong (*page, GWL_EXSTYLE) |
1362 WS_EX_CONTROLPARENT);
1363 }
1364 SetFocus (*page);
1365 return 0;
1366 case WM_NOTIFY:
1367 if (LOWORD(wParam) == IDC_TAB &&
1368 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1369 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1370 if (*page)
1371 DestroyWindow (*page);
1372 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1373 hwnd, panelproc[panelnums[i]]);*/
1374 *page = CreateDialog (hinst, panelids[panelnums[i]],
1375 hwnd, panelproc[panelnums[i]]);
1376 SetWindowLong (*page, GWL_EXSTYLE,
1377 GetWindowLong (*page, GWL_EXSTYLE) |
1378 WS_EX_CONTROLPARENT);
1379 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1380 return 0;
1381 }
1382 break;
1383 /* case WM_CTLCOLORDLG: */
1384 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1385 case WM_COMMAND:
1386 switch (LOWORD(wParam)) {
1387 case IDOK:
1388 if (*cfg.host)
1389 EndDialog (hwnd, 1);
1390 else
1391 MessageBeep (0);
1392 return 0;
1393 case IDCANCEL:
1394 EndDialog (hwnd, 0);
1395 return 0;
1396 }
1397 return 0;
1398 case WM_CLOSE:
1399 EndDialog (hwnd, 0);
1400 return 0;
1401
1402 /* Grrr Explorer will maximize Dialogs! */
1403 case WM_SIZE:
1404 if (wParam == SIZE_MAXIMIZED)
1405 force_normal(hwnd);
1406 return 0;
1407 }
1408 return 0;
1409 }
1410
1411 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1412 WPARAM wParam, LPARAM lParam) {
1413 #if 0
1414 HWND hw;
1415 int i;
1416 #endif
1417 static HWND page = NULL;
1418
1419 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1420 #if 0
1421 /*
1422 * If the Connection panel is active and the Session List
1423 * box is selected, we treat a press of Open to have an
1424 * implicit press of Load preceding it.
1425 */
1426 hw = GetDlgItem (hwnd, IDC_TAB);
1427 i = TabCtrl_GetCurSel(hw);
1428 if (panelproc[mainp[i]] == ConnectionProc &&
1429 page && implicit_load_ok) {
1430 SendMessage (page, WM_COMMAND,
1431 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1432 }
1433 #endif
1434 }
1435 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1436 EnableWindow(hwnd, 0);
1437 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1438 GetParent(hwnd), AboutProc);
1439 EnableWindow(hwnd, 1);
1440 SetActiveWindow(hwnd);
1441 }
1442 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1443 MAIN_NPANELS, mainp, &page);
1444 }
1445
1446 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1447 WPARAM wParam, LPARAM lParam) {
1448 static HWND page;
1449 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1450 RECONF_NPANELS, reconfp, &page);
1451 }
1452
1453 void get_sesslist(int allocate) {
1454 static char otherbuf[2048];
1455 static char *buffer;
1456 int buflen, bufsize, i;
1457 char *p, *ret;
1458 void *handle;
1459
1460 if (allocate) {
1461
1462 if ((handle = enum_settings_start()) == NULL)
1463 return;
1464
1465 buflen = bufsize = 0;
1466 buffer = NULL;
1467 do {
1468 ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
1469 if (ret) {
1470 int len = strlen(otherbuf)+1;
1471 if (bufsize < buflen+len) {
1472 bufsize = buflen + len + 2048;
1473 buffer = srealloc(buffer, bufsize);
1474 }
1475 strcpy(buffer+buflen, otherbuf);
1476 buflen += strlen(buffer+buflen)+1;
1477 }
1478 } while (ret);
1479 enum_settings_finish(handle);
1480 buffer = srealloc(buffer, buflen+1);
1481 buffer[buflen] = '\0';
1482
1483 p = buffer;
1484 nsessions = 1; /* "Default Settings" counts as one */
1485 while (*p) {
1486 if (strcmp(p, "Default Settings"))
1487 nsessions++;
1488 while (*p) p++;
1489 p++;
1490 }
1491
1492 sessions = smalloc(nsessions * sizeof(char *));
1493 sessions[0] = "Default Settings";
1494 p = buffer;
1495 i = 1;
1496 while (*p) {
1497 if (strcmp(p, "Default Settings"))
1498 sessions[i++] = p;
1499 while (*p) p++;
1500 p++;
1501 }
1502 } else {
1503 sfree (buffer);
1504 sfree (sessions);
1505 }
1506 }
1507
1508 int do_config (void) {
1509 int ret;
1510
1511 get_sesslist(TRUE);
1512 savedsession[0] = '\0';
1513 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1514 get_sesslist(FALSE);
1515
1516 return ret;
1517 }
1518
1519 int do_reconfig (HWND hwnd) {
1520 Config backup_cfg;
1521 int ret;
1522
1523 backup_cfg = cfg; /* structure copy */
1524 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1525 if (!ret)
1526 cfg = backup_cfg; /* structure copy */
1527 else
1528 force_normal(hwnd);
1529
1530 return ret;
1531 }
1532
1533 void do_defaults (char *session) {
1534 if (session)
1535 load_settings (session, TRUE);
1536 else
1537 load_settings ("Default Settings", FALSE);
1538 }
1539
1540 void logevent (char *string) {
1541 if (nevents >= negsize) {
1542 negsize += 64;
1543 events = srealloc (events, negsize * sizeof(*events));
1544 }
1545 events[nevents] = smalloc(1+strlen(string));
1546 strcpy (events[nevents], string);
1547 nevents++;
1548 if (logbox) {
1549 int count;
1550 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1551 0, (LPARAM)string);
1552 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1553 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1554 }
1555 }
1556
1557 void showeventlog (HWND hwnd) {
1558 if (!logbox) {
1559 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1560 hwnd, LogProc);
1561 ShowWindow (logbox, SW_SHOWNORMAL);
1562 }
1563 }
1564
1565 void showabout (HWND hwnd) {
1566 if (!abtbox) {
1567 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1568 hwnd, AboutProc);
1569 ShowWindow (abtbox, SW_SHOWNORMAL);
1570 }
1571 }
1572
1573 void verify_ssh_host_key(char *host, int port, char *keytype,
1574 char *keystr, char *fingerprint) {
1575 int ret;
1576
1577 static const char absentmsg[] =
1578 "The server's host key is not cached in the registry. You\n"
1579 "have no guarantee that the server is the computer you\n"
1580 "think it is.\n"
1581 "The server's key fingerprint is:\n"
1582 "%s\n"
1583 "If you trust this host, hit Yes to add the key to\n"
1584 "PuTTY's cache and carry on connecting.\n"
1585 "If you do not trust this host, hit No to abandon the\n"
1586 "connection.\n";
1587
1588 static const char wrongmsg[] =
1589 "WARNING - POTENTIAL SECURITY BREACH!\n"
1590 "\n"
1591 "The server's host key does not match the one PuTTY has\n"
1592 "cached in the registry. This means that either the\n"
1593 "server administrator has changed the host key, or you\n"
1594 "have actually connected to another computer pretending\n"
1595 "to be the server.\n"
1596 "The new key fingerprint is:\n"
1597 "%s\n"
1598 "If you were expecting this change and trust the new key,\n"
1599 "hit Yes to update PuTTY's cache and continue connecting.\n"
1600 "If you want to carry on connecting but without updating\n"
1601 "the cache, hit No.\n"
1602 "If you want to abandon the connection completely, hit\n"
1603 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1604 "choice.\n";
1605
1606 static const char mbtitle[] = "PuTTY Security Alert";
1607
1608
1609 char message[160+ /* sensible fingerprint max size */
1610 (sizeof(absentmsg) > sizeof(wrongmsg) ?
1611 sizeof(absentmsg) : sizeof(wrongmsg))];
1612
1613 /*
1614 * Verify the key against the registry.
1615 */
1616 ret = verify_host_key(host, port, keytype, keystr);
1617
1618 if (ret == 0) /* success - key matched OK */
1619 return;
1620 if (ret == 2) { /* key was different */
1621 int mbret;
1622 sprintf(message, wrongmsg, fingerprint);
1623 mbret = MessageBox(NULL, message, mbtitle,
1624 MB_ICONWARNING | MB_YESNOCANCEL);
1625 if (mbret == IDYES)
1626 store_host_key(host, port, keytype, keystr);
1627 if (mbret == IDCANCEL)
1628 exit(0);
1629 }
1630 if (ret == 1) { /* key was absent */
1631 int mbret;
1632 sprintf(message, absentmsg, fingerprint);
1633 mbret = MessageBox(NULL, message, mbtitle,
1634 MB_ICONWARNING | MB_YESNO);
1635 if (mbret == IDNO)
1636 exit(0);
1637 store_host_key(host, port, keytype, keystr);
1638 }
1639 }