8a200e91b5a34701468086707ad860256ae52bfc
[u/mdw/putty] / windlg.c
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <commdlg.h>
4 #include <winsock.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include "ssh.h"
9 #include "putty.h"
10 #include "win_res.h"
11
12 #define NPANELS 7
13 #define MAIN_NPANELS 7
14 #define RECONF_NPANELS 4
15
16 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
17
18 static char **negots = NULL;
19 static int nnegots = 0, negsize = 0;
20 static HWND logbox = NULL, abtbox = NULL;
21
22 static char hex[16] = "0123456789ABCDEF";
23
24 static void mungestr(char *in, char *out) {
25 int candot = 0;
26
27 while (*in) {
28 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
29 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
30 *out++ = '%';
31 *out++ = hex[((unsigned char)*in) >> 4];
32 *out++ = hex[((unsigned char)*in) & 15];
33 } else
34 *out++ = *in;
35 in++;
36 candot = 1;
37 }
38 *out = '\0';
39 return;
40 }
41
42 static void unmungestr(char *in, char *out) {
43 while (*in) {
44 if (*in == '%' && in[1] && in[2]) {
45 int i, j;
46
47 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
48 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
49
50 *out++ = (i<<4) + j;
51 in += 3;
52 } else
53 *out++ = *in++;
54 }
55 *out = '\0';
56 return;
57 }
58
59 static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
60 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
61 }
62
63 static void wppi(HKEY key, LPCTSTR name, int value) {
64 RegSetValueEx(key, name, 0, REG_DWORD,
65 (CONST BYTE *)&value, sizeof(value));
66 }
67
68 static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
69 LPTSTR val, int len) {
70 DWORD type, size;
71 size = len;
72
73 if (key == NULL ||
74 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
75 type != REG_SZ) {
76 strncpy(val, def, len);
77 val[len-1] = '\0';
78 }
79 }
80
81 static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
82 DWORD type, val, size;
83 size = sizeof(val);
84
85 if (key == NULL ||
86 RegQueryValueEx(key, name, 0, &type,
87 (BYTE *)&val, &size) != ERROR_SUCCESS ||
88 size != sizeof(val) || type != REG_DWORD)
89 *i = def;
90 else
91 *i = val;
92 }
93
94 static HINSTANCE hinst;
95
96 static int readytogo;
97
98 static void save_settings (char *section, int do_host) {
99 int i;
100 HKEY subkey1, sesskey;
101 char *p;
102
103 p = malloc(3*strlen(section)+1);
104 mungestr(section, p);
105
106 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
107 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
108 sesskey = NULL;
109 }
110
111 free(p);
112 RegCloseKey(subkey1);
113
114 wppi (sesskey, "Present", 1);
115 if (do_host) {
116 wpps (sesskey, "HostName", cfg.host);
117 wppi (sesskey, "PortNumber", cfg.port);
118 wpps (sesskey, "Protocol",
119 cfg.protocol == PROT_SSH ? "ssh" : "telnet");
120 }
121 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
122 wpps (sesskey, "TerminalType", cfg.termtype);
123 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
124 {
125 char buf[2*sizeof(cfg.environmt)], *p, *q;
126 p = buf;
127 q = cfg.environmt;
128 while (*q) {
129 while (*q) {
130 int c = *q++;
131 if (c == '=' || c == ',' || c == '\\')
132 *p++ = '\\';
133 if (c == '\t')
134 c = '=';
135 *p++ = c;
136 }
137 *p++ = ',';
138 q++;
139 }
140 *p = '\0';
141 wpps (sesskey, "Environment", buf);
142 }
143 wpps (sesskey, "UserName", cfg.username);
144 wppi (sesskey, "NoPTY", cfg.nopty);
145 wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
146 cfg.cipher == CIPHER_DES ? "des" : "3des");
147 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
148 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
149 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
150 wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
151 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
152 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
153 wppi (sesskey, "ScrollbackLines", cfg.savelines);
154 wppi (sesskey, "DECOriginMode", cfg.dec_om);
155 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
156 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
157 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
158 wppi (sesskey, "TermWidth", cfg.width);
159 wppi (sesskey, "TermHeight", cfg.height);
160 wpps (sesskey, "Font", cfg.font);
161 wppi (sesskey, "FontIsBold", cfg.fontisbold);
162 wppi (sesskey, "FontHeight", cfg.fontheight);
163 wppi (sesskey, "FontVTMode", cfg.vtmode);
164 wppi (sesskey, "TryPalette", cfg.try_palette);
165 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
166 for (i=0; i<22; i++) {
167 char buf[20], buf2[30];
168 sprintf(buf, "Colour%d", i);
169 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
170 cfg.colours[i][1], cfg.colours[i][2]);
171 wpps (sesskey, buf, buf2);
172 }
173 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
174 for (i=0; i<256; i+=32) {
175 char buf[20], buf2[256];
176 int j;
177 sprintf(buf, "Wordness%d", i);
178 *buf2 = '\0';
179 for (j=i; j<i+32; j++) {
180 sprintf(buf2+strlen(buf2), "%s%d",
181 (*buf2 ? "," : ""), cfg.wordness[j]);
182 }
183 wpps (sesskey, buf, buf2);
184 }
185
186 RegCloseKey(sesskey);
187 }
188
189 static void del_session (char *section) {
190 HKEY subkey1;
191 char *p;
192
193 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
194 return;
195
196 p = malloc(3*strlen(section)+1);
197 mungestr(section, p);
198 RegDeleteKey(subkey1, p);
199 free(p);
200
201 RegCloseKey(subkey1);
202 }
203
204 static void load_settings (char *section, int do_host) {
205 int i;
206 HKEY subkey1, sesskey;
207 char *p;
208 char prot[10];
209
210 p = malloc(3*strlen(section)+1);
211 mungestr(section, p);
212
213 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
214 sesskey = NULL;
215 } else {
216 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
217 sesskey = NULL;
218 }
219 RegCloseKey(subkey1);
220 }
221
222 free(p);
223
224 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
225 gppi (sesskey, "PortNumber", default_port, &cfg.port);
226 gpps (sesskey, "Protocol", "default", prot, 10);
227 if (!strcmp(prot, "ssh"))
228 cfg.protocol = PROT_SSH;
229 else if (!strcmp(prot, "telnet"))
230 cfg.protocol = PROT_TELNET;
231 else
232 cfg.protocol = default_protocol;
233
234 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
235 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
236 sizeof(cfg.termtype));
237 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
238 sizeof(cfg.termspeed));
239 {
240 char buf[2*sizeof(cfg.environmt)], *p, *q;
241 gpps (sesskey, "Environment", "", buf, sizeof(buf));
242 p = buf;
243 q = cfg.environmt;
244 while (*p) {
245 while (*p && *p != ',') {
246 int c = *p++;
247 if (c == '=')
248 c = '\t';
249 if (c == '\\')
250 c = *p++;
251 *p++ = c;
252 }
253 if (*p == ',') p++;
254 *q++ = '\0';
255 }
256 *q = '\0';
257 }
258 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
259 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
260 {
261 char cipher[10];
262 gpps (sesskey, "Cipher", "3des", cipher, 10);
263 if (!strcmp(cipher, "blowfish"))
264 cfg.cipher = CIPHER_BLOWFISH;
265 else if (!strcmp(cipher, "des"))
266 cfg.cipher = CIPHER_DES;
267 else
268 cfg.cipher = CIPHER_3DES;
269 }
270 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
271 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
272 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
273 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
274 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
275 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
276 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
277 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
278 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
279 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
280 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
281 gppi (sesskey, "TermWidth", 80, &cfg.width);
282 gppi (sesskey, "TermHeight", 24, &cfg.height);
283 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
284 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
285 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
286 gppi (sesskey, "FontVTMode", VT_POORMAN, &cfg.vtmode);
287 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
288 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
289 for (i=0; i<22; i++) {
290 static char *defaults[] = {
291 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
292 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
293 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
294 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
295 "85,255,255", "187,187,187", "255,255,255"
296 };
297 char buf[20], buf2[30];
298 sprintf(buf, "Colour%d", i);
299 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
300 sscanf(buf2, "%d,%d,%d", &cfg.colours[i][0],
301 &cfg.colours[i][1], &cfg.colours[i][2]);
302 }
303 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
304 for (i=0; i<256; i+=32) {
305 static char *defaults[] = {
306 "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",
307 "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",
308 "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",
309 "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",
310 "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",
311 "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",
312 "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",
313 "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"
314 };
315 char buf[20], buf2[256], *p;
316 int j;
317 sprintf(buf, "Wordness%d", i);
318 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
319 p = buf2;
320 for (j=i; j<i+32; j++) {
321 char *q = p;
322 while (*p && *p != ',') p++;
323 if (*p == ',') *p++ = '\0';
324 cfg.wordness[j] = atoi(q);
325 }
326 }
327 RegCloseKey(sesskey);
328 }
329
330 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
331 BOOL ok;
332 int n;
333 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
334 if (ok)
335 *result = n;
336 }
337
338 static int CALLBACK LogProc (HWND hwnd, UINT msg,
339 WPARAM wParam, LPARAM lParam) {
340 int i;
341
342 switch (msg) {
343 case WM_INITDIALOG:
344 for (i=0; i<nnegots; i++)
345 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
346 0, (LPARAM)negots[i]);
347 return 1;
348 /* case WM_CTLCOLORDLG: */
349 /* return (int) GetStockObject (LTGRAY_BRUSH); */
350 case WM_COMMAND:
351 switch (LOWORD(wParam)) {
352 case IDOK:
353 logbox = NULL;
354 DestroyWindow (hwnd);
355 return 0;
356 }
357 return 0;
358 case WM_CLOSE:
359 logbox = NULL;
360 DestroyWindow (hwnd);
361 return 0;
362 }
363 return 0;
364 }
365
366 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
367 WPARAM wParam, LPARAM lParam) {
368 switch (msg) {
369 case WM_INITDIALOG:
370 return 1;
371 case WM_COMMAND:
372 switch (LOWORD(wParam)) {
373 case IDOK:
374 abtbox = NULL;
375 DestroyWindow (hwnd);
376 return 0;
377 }
378 return 0;
379 case WM_CLOSE:
380 abtbox = NULL;
381 DestroyWindow (hwnd);
382 return 0;
383 }
384 return 0;
385 }
386
387 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
388 WPARAM wParam, LPARAM lParam) {
389 switch (msg) {
390 case WM_INITDIALOG:
391 SetDlgItemText (hwnd, IDA_VERSION, ver);
392 return 1;
393 /* case WM_CTLCOLORDLG: */
394 /* return (int) GetStockObject (LTGRAY_BRUSH); */
395 /* case WM_CTLCOLORSTATIC: */
396 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
397 /* return (int) GetStockObject (LTGRAY_BRUSH); */
398 case WM_COMMAND:
399 switch (LOWORD(wParam)) {
400 case IDOK:
401 abtbox = NULL;
402 DestroyWindow (hwnd);
403 return 0;
404 case IDA_LICENCE:
405 EnableWindow(hwnd, 0);
406 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
407 NULL, LicenceProc);
408 EnableWindow(hwnd, 1);
409 return 0;
410 }
411 return 0;
412 case WM_CLOSE:
413 abtbox = NULL;
414 DestroyWindow (hwnd);
415 return 0;
416 }
417 return 0;
418 }
419
420 static int GeneralPanelProc (HWND hwnd, UINT msg,
421 WPARAM wParam, LPARAM lParam) {
422 switch (msg) {
423 case WM_INITDIALOG:
424 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
425 return 1;
426 /* case WM_CTLCOLORDLG: */
427 /* return (int) GetStockObject (LTGRAY_BRUSH); */
428 /* case WM_CTLCOLORSTATIC: */
429 /* case WM_CTLCOLORBTN: */
430 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
431 /* return (int) GetStockObject (LTGRAY_BRUSH); */
432 case WM_CLOSE:
433 DestroyWindow (hwnd);
434 return 1;
435 }
436 return 0;
437 }
438
439 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
440 WPARAM wParam, LPARAM lParam) {
441 int i;
442
443 switch (msg) {
444 case WM_INITDIALOG:
445 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
446 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
447 for (i = 0; i < nsessions; i++)
448 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
449 0, (LPARAM) (sessions[i]));
450 CheckRadioButton (hwnd, IDC0_PROTTELNET, IDC0_PROTSSH,
451 cfg.protocol==PROT_SSH ? IDC0_PROTSSH : IDC0_PROTTELNET);
452 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
453 break;
454 case WM_LBUTTONUP:
455 /*
456 * Button release should trigger WM_OK if there was a
457 * previous double click on the session list.
458 */
459 ReleaseCapture();
460 if (readytogo)
461 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
462 break;
463 case WM_COMMAND:
464 switch (LOWORD(wParam)) {
465 case IDC0_PROTTELNET:
466 case IDC0_PROTSSH:
467 if (HIWORD(wParam) == BN_CLICKED ||
468 HIWORD(wParam) == BN_DOUBLECLICKED) {
469 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
470 cfg.protocol = i ? PROT_SSH : PROT_TELNET;
471 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
472 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
473 cfg.port = i ? 22 : 23;
474 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
475 }
476 }
477 break;
478 case IDC0_HOST:
479 if (HIWORD(wParam) == EN_CHANGE)
480 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
481 sizeof(cfg.host)-1);
482 break;
483 case IDC0_PORT:
484 if (HIWORD(wParam) == EN_CHANGE)
485 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
486 break;
487 case IDC0_CLOSEEXIT:
488 if (HIWORD(wParam) == BN_CLICKED ||
489 HIWORD(wParam) == BN_DOUBLECLICKED)
490 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
491 break;
492 case IDC0_SESSEDIT:
493 if (HIWORD(wParam) == EN_CHANGE)
494 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
495 (WPARAM) -1, 0);
496 break;
497 case IDC0_SESSSAVE:
498 if (HIWORD(wParam) == BN_CLICKED ||
499 HIWORD(wParam) == BN_DOUBLECLICKED) {
500 /*
501 * Save a session
502 */
503 char str[2048];
504 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
505 if (!*str) {
506 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
507 LB_GETCURSEL, 0, 0);
508 if (n == LB_ERR) {
509 MessageBeep(0);
510 break;
511 }
512 strcpy (str, sessions[n]);
513 }
514 save_settings (str, !!strcmp(str, "Default Settings"));
515 get_sesslist (FALSE);
516 get_sesslist (TRUE);
517 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
518 0, 0);
519 for (i = 0; i < nsessions; i++)
520 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
521 0, (LPARAM) (sessions[i]));
522 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
523 (WPARAM) -1, 0);
524 }
525 break;
526 case IDC0_SESSLIST:
527 case IDC0_SESSLOAD:
528 if (LOWORD(wParam) == IDC0_SESSLOAD &&
529 HIWORD(wParam) != BN_CLICKED &&
530 HIWORD(wParam) != BN_DOUBLECLICKED)
531 break;
532 if (LOWORD(wParam) == IDC0_SESSLIST &&
533 HIWORD(wParam) != LBN_DBLCLK)
534 break;
535 {
536 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
537 LB_GETCURSEL, 0, 0);
538 if (n == LB_ERR) {
539 MessageBeep(0);
540 break;
541 }
542 load_settings (sessions[n],
543 !!strcmp(sessions[n], "Default Settings"));
544 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
545 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
546 CheckRadioButton (hwnd, IDC0_PROTTELNET, IDC0_PROTSSH,
547 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
548 IDC0_PROTTELNET));
549 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
550 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
551 (WPARAM) -1, 0);
552 }
553 if (LOWORD(wParam) == IDC0_SESSLIST) {
554 /*
555 * A double-click on a saved session should
556 * actually start the session, not just load it.
557 * Unless it's Default Settings or some other
558 * host-less set of saved settings.
559 */
560 if (*cfg.host) {
561 readytogo = TRUE;
562 SetCapture(hwnd);
563 }
564 }
565 break;
566 case IDC0_SESSDEL:
567 if (HIWORD(wParam) == BN_CLICKED ||
568 HIWORD(wParam) == BN_DOUBLECLICKED) {
569 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
570 LB_GETCURSEL, 0, 0);
571 if (n == LB_ERR || n == 0) {
572 MessageBeep(0);
573 break;
574 }
575 del_session(sessions[n]);
576 get_sesslist (FALSE);
577 get_sesslist (TRUE);
578 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
579 0, 0);
580 for (i = 0; i < nsessions; i++)
581 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
582 0, (LPARAM) (sessions[i]));
583 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
584 (WPARAM) -1, 0);
585 }
586 }
587 }
588 return GeneralPanelProc (hwnd, msg, wParam, lParam);
589 }
590
591 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
592 WPARAM wParam, LPARAM lParam) {
593 switch (msg) {
594 case WM_INITDIALOG:
595 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
596 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
597 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
598 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
599 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
600 cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
601 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
602 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
603 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPAPPLIC,
604 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
605 break;
606 case WM_COMMAND:
607 if (HIWORD(wParam) == BN_CLICKED ||
608 HIWORD(wParam) == BN_DOUBLECLICKED)
609 switch (LOWORD(wParam)) {
610 case IDC1_DEL008:
611 case IDC1_DEL127:
612 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
613 break;
614 case IDC1_HOMETILDE:
615 case IDC1_HOMERXVT:
616 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
617 break;
618 case IDC1_FUNCTILDE:
619 case IDC1_FUNCLINUX:
620 cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
621 break;
622 case IDC1_KPNORMAL:
623 case IDC1_KPAPPLIC:
624 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
625 break;
626 case IDC1_CURNORMAL:
627 case IDC1_CURAPPLIC:
628 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
629 break;
630 }
631 }
632 return GeneralPanelProc (hwnd, msg, wParam, lParam);
633 }
634
635 static void fmtfont (char *buf) {
636 sprintf (buf, "Font: %s, ", cfg.font);
637 if (cfg.fontisbold)
638 strcat(buf, "bold, ");
639 if (cfg.fontheight == 0)
640 strcat (buf, "default height");
641 else
642 sprintf (buf+strlen(buf), "%d-%s",
643 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
644 (cfg.fontheight < 0 ? "pixel" : "point"));
645 }
646
647 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
648 WPARAM wParam, LPARAM lParam) {
649 CHOOSEFONT cf;
650 LOGFONT lf;
651 char fontstatic[256];
652
653 switch (msg) {
654 case WM_INITDIALOG:
655 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
656 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
657 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
658 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
659 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
660 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
661 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
662 fmtfont (fontstatic);
663 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
664 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
665 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
666 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
667 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
668 IDC2_VTPOORMAN);
669 break;
670 case WM_COMMAND:
671 switch (LOWORD(wParam)) {
672 case IDC2_WRAPMODE:
673 if (HIWORD(wParam) == BN_CLICKED ||
674 HIWORD(wParam) == BN_DOUBLECLICKED)
675 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
676 break;
677 case IDC2_WINNAME:
678 if (HIWORD(wParam) == BN_CLICKED ||
679 HIWORD(wParam) == BN_DOUBLECLICKED)
680 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
681 break;
682 case IDC2_DECOM:
683 if (HIWORD(wParam) == BN_CLICKED ||
684 HIWORD(wParam) == BN_DOUBLECLICKED)
685 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
686 break;
687 case IDC2_LFHASCR:
688 if (HIWORD(wParam) == BN_CLICKED ||
689 HIWORD(wParam) == BN_DOUBLECLICKED)
690 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
691 break;
692 case IDC2_ROWSEDIT:
693 if (HIWORD(wParam) == EN_CHANGE)
694 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
695 break;
696 case IDC2_COLSEDIT:
697 if (HIWORD(wParam) == EN_CHANGE)
698 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
699 break;
700 case IDC2_SAVEEDIT:
701 if (HIWORD(wParam) == EN_CHANGE)
702 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
703 break;
704 case IDC2_CHOOSEFONT:
705 lf.lfHeight = cfg.fontheight;
706 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
707 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
708 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
709 lf.lfCharSet = ANSI_CHARSET;
710 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
711 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
712 lf.lfQuality = DEFAULT_QUALITY;
713 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
714 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
715 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
716
717 cf.lStructSize = sizeof(cf);
718 cf.hwndOwner = hwnd;
719 cf.lpLogFont = &lf;
720 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
721 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
722
723 if (ChooseFont (&cf)) {
724 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
725 cfg.font[sizeof(cfg.font)-1] = '\0';
726 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
727 cfg.fontheight = lf.lfHeight;
728 fmtfont (fontstatic);
729 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
730 }
731 break;
732 case IDC2_VTXWINDOWS:
733 case IDC2_VTOEMANSI:
734 case IDC2_VTOEMONLY:
735 case IDC2_VTPOORMAN:
736 cfg.vtmode =
737 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
738 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
739 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
740 VT_POORMAN);
741 break;
742 }
743 break;
744 }
745 return GeneralPanelProc (hwnd, msg, wParam, lParam);
746 }
747
748 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
749 WPARAM wParam, LPARAM lParam) {
750 int i;
751
752 switch (msg) {
753 case WM_INITDIALOG:
754 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
755 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
756 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
757 {
758 char *p = cfg.environmt;
759 while (*p) {
760 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
761 (LPARAM) p);
762 p += strlen(p)+1;
763 }
764 }
765 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
766 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
767 break;
768 case WM_COMMAND:
769 switch (LOWORD(wParam)) {
770 case IDC3_TTEDIT:
771 if (HIWORD(wParam) == EN_CHANGE)
772 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
773 sizeof(cfg.termtype)-1);
774 break;
775 case IDC3_TSEDIT:
776 if (HIWORD(wParam) == EN_CHANGE)
777 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
778 sizeof(cfg.termspeed)-1);
779 break;
780 case IDC3_LOGEDIT:
781 if (HIWORD(wParam) == EN_CHANGE)
782 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
783 sizeof(cfg.username)-1);
784 break;
785 case IDC3_EMBSD:
786 case IDC3_EMRFC:
787 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
788 break;
789 case IDC3_ENVADD:
790 if (HIWORD(wParam) == BN_CLICKED ||
791 HIWORD(wParam) == BN_DOUBLECLICKED) {
792 char str[sizeof(cfg.environmt)];
793 char *p;
794 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
795 if (!*str) {
796 MessageBeep(0);
797 break;
798 }
799 p = str + strlen(str);
800 *p++ = '\t';
801 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
802 if (!*p) {
803 MessageBeep(0);
804 break;
805 }
806 p = cfg.environmt;
807 while (*p) {
808 while (*p) p++;
809 p++;
810 }
811 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
812 strcpy (p, str);
813 p[strlen(str)+1] = '\0';
814 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
815 0, (LPARAM)str);
816 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
817 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
818 } else {
819 MessageBox(hwnd, "Environment too big", "PuTTY Error",
820 MB_OK | MB_ICONERROR);
821 }
822 }
823 break;
824 case IDC3_ENVREMOVE:
825 if (HIWORD(wParam) != BN_CLICKED &&
826 HIWORD(wParam) != BN_DOUBLECLICKED)
827 break;
828 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
829 if (i == LB_ERR)
830 MessageBeep (0);
831 else {
832 char *p, *q;
833
834 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
835 i, 0);
836 p = cfg.environmt;
837 while (i > 0) {
838 if (!*p)
839 goto disaster;
840 while (*p) p++;
841 p++;
842 i--;
843 }
844 q = p;
845 if (!*p)
846 goto disaster;
847 while (*p) p++;
848 p++;
849 while (*p) {
850 while (*p)
851 *q++ = *p++;
852 *q++ = *p++;
853 }
854 *q = '\0';
855 disaster:;
856 }
857 break;
858 }
859 break;
860 }
861 return GeneralPanelProc (hwnd, msg, wParam, lParam);
862 }
863
864 static int CALLBACK SshProc (HWND hwnd, UINT msg,
865 WPARAM wParam, LPARAM lParam) {
866 switch (msg) {
867 case WM_INITDIALOG:
868 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
869 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
870 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
871 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
872 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
873 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
874
875 IDC3_CIPHER3DES);
876 break;
877 case WM_COMMAND:
878 switch (LOWORD(wParam)) {
879 case IDC3_TTEDIT:
880 if (HIWORD(wParam) == EN_CHANGE)
881 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
882 sizeof(cfg.termtype)-1);
883 break;
884 case IDC3_LOGEDIT:
885 if (HIWORD(wParam) == EN_CHANGE)
886 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
887 sizeof(cfg.username)-1);
888 break;
889 case IDC3_NOPTY:
890 if (HIWORD(wParam) == BN_CLICKED ||
891 HIWORD(wParam) == BN_DOUBLECLICKED)
892 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
893 break;
894 case IDC3_CIPHER3DES:
895 case IDC3_CIPHERBLOWF:
896 case IDC3_CIPHERDES:
897 if (HIWORD(wParam) == BN_CLICKED ||
898 HIWORD(wParam) == BN_DOUBLECLICKED) {
899 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
900 cfg.cipher = CIPHER_3DES;
901 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
902 cfg.cipher = CIPHER_BLOWFISH;
903 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
904 cfg.cipher = CIPHER_DES;
905 }
906 break;
907 }
908 break;
909 }
910 return GeneralPanelProc (hwnd, msg, wParam, lParam);
911 }
912
913 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
914 WPARAM wParam, LPARAM lParam) {
915 int i;
916
917 switch (msg) {
918 case WM_INITDIALOG:
919 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
920 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
921 {
922 static int tabs[4] = {25, 61, 96, 128};
923 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
924 (LPARAM) tabs);
925 }
926 for (i=0; i<256; i++) {
927 char str[100];
928 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
929 (i>=0x21 && i != 0x7F) ? i : ' ',
930 cfg.wordness[i]);
931 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
932 (LPARAM) str);
933 }
934 break;
935 case WM_COMMAND:
936 switch (LOWORD(wParam)) {
937 case IDC4_MBWINDOWS:
938 case IDC4_MBXTERM:
939 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
940 break;
941 case IDC4_CCSET:
942 {
943 BOOL ok;
944 int i;
945 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
946
947 if (!ok)
948 MessageBeep (0);
949 else {
950 for (i=0; i<256; i++)
951 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
952 i, 0)) {
953 char str[100];
954 cfg.wordness[i] = n;
955 SendDlgItemMessage (hwnd, IDC4_CCLIST,
956 LB_DELETESTRING, i, 0);
957 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
958 (i>=0x21 && i != 0x7F) ? i : ' ',
959 cfg.wordness[i]);
960 SendDlgItemMessage (hwnd, IDC4_CCLIST,
961 LB_INSERTSTRING, i,
962 (LPARAM)str);
963 }
964 }
965 }
966 break;
967 }
968 break;
969 }
970 return GeneralPanelProc (hwnd, msg, wParam, lParam);
971 }
972
973 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
974 WPARAM wParam, LPARAM lParam) {
975 static const char *const colours[] = {
976 "Default Foreground", "Default Bold Foreground",
977 "Default Background", "Default Bold Background",
978 "Cursor Text", "Cursor Colour",
979 "ANSI Black", "ANSI Black Bold",
980 "ANSI Red", "ANSI Red Bold",
981 "ANSI Green", "ANSI Green Bold",
982 "ANSI Yellow", "ANSI Yellow Bold",
983 "ANSI Blue", "ANSI Blue Bold",
984 "ANSI Magenta", "ANSI Magenta Bold",
985 "ANSI Cyan", "ANSI Cyan Bold",
986 "ANSI White", "ANSI White Bold"
987 };
988 static const int permanent[] = {
989 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
990 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
991 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
992 };
993 switch (msg) {
994 case WM_INITDIALOG:
995 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
996 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
997 {
998 int i;
999 for (i=0; i<22; i++)
1000 if (cfg.bold_colour || permanent[i])
1001 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1002 (LPARAM) colours[i]);
1003 }
1004 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1005 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1006 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1007 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1008 break;
1009 case WM_COMMAND:
1010 switch (LOWORD(wParam)) {
1011 case IDC5_BOLDCOLOUR:
1012 if (HIWORD(wParam) == BN_CLICKED ||
1013 HIWORD(wParam) == BN_DOUBLECLICKED) {
1014 int n, i;
1015 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1016 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1017 if (cfg.bold_colour && n!=22) {
1018 for (i=0; i<22; i++)
1019 if (!permanent[i])
1020 SendDlgItemMessage (hwnd, IDC5_LIST,
1021 LB_INSERTSTRING, i,
1022 (LPARAM) colours[i]);
1023 } else if (!cfg.bold_colour && n!=12) {
1024 for (i=22; i-- ;)
1025 if (!permanent[i])
1026 SendDlgItemMessage (hwnd, IDC5_LIST,
1027 LB_DELETESTRING, i, 0);
1028 }
1029 }
1030 break;
1031 case IDC5_PALETTE:
1032 if (HIWORD(wParam) == BN_CLICKED ||
1033 HIWORD(wParam) == BN_DOUBLECLICKED)
1034 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1035 break;
1036 case IDC5_LIST:
1037 if (HIWORD(wParam) == LBN_DBLCLK ||
1038 HIWORD(wParam) == LBN_SELCHANGE) {
1039 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1040 0, 0);
1041 if (!cfg.bold_colour)
1042 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1043 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1044 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1045 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1046 }
1047 break;
1048 case IDC5_CHANGE:
1049 if (HIWORD(wParam) == BN_CLICKED ||
1050 HIWORD(wParam) == BN_DOUBLECLICKED) {
1051 static CHOOSECOLOR cc;
1052 static DWORD custom[16] = {0}; /* zero initialisers */
1053 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1054 0, 0);
1055 if (!cfg.bold_colour)
1056 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1057 cc.lStructSize = sizeof(cc);
1058 cc.hwndOwner = hwnd;
1059 cc.hInstance = hinst;
1060 cc.lpCustColors = custom;
1061 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1062 cfg.colours[i][2]);
1063 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1064 if (ChooseColor(&cc)) {
1065 cfg.colours[i][0] =
1066 (unsigned char) (cc.rgbResult & 0xFF);
1067 cfg.colours[i][1] =
1068 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1069 cfg.colours[i][2] =
1070 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1071 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1072 FALSE);
1073 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1074 FALSE);
1075 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1076 FALSE);
1077 }
1078 }
1079 break;
1080 }
1081 break;
1082 }
1083 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1084 }
1085
1086 static DLGPROC panelproc[NPANELS] = {
1087 ConnectionProc, KeyboardProc, TerminalProc,
1088 TelnetProc, SshProc, SelectionProc, ColourProc
1089 };
1090 static char *panelids[NPANELS] = {
1091 MAKEINTRESOURCE(IDD_PANEL0),
1092 MAKEINTRESOURCE(IDD_PANEL1),
1093 MAKEINTRESOURCE(IDD_PANEL2),
1094 MAKEINTRESOURCE(IDD_PANEL3),
1095 MAKEINTRESOURCE(IDD_PANEL35),
1096 MAKEINTRESOURCE(IDD_PANEL4),
1097 MAKEINTRESOURCE(IDD_PANEL5)
1098 };
1099 static char *names[NPANELS] = {
1100 "Connection", "Keyboard", "Terminal", "Telnet", "SSH", "Selection", "Colours"
1101 };
1102
1103 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6 };
1104 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6 };
1105
1106 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1107 WPARAM wParam, LPARAM lParam,
1108 int npanels, int *panelnums, HWND *page) {
1109 HWND hw;
1110
1111 switch (msg) {
1112 case WM_INITDIALOG:
1113 { /* centre the window */
1114 RECT rs, rd;
1115
1116 hw = GetDesktopWindow();
1117 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1118 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1119 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1120 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1121 }
1122 *page = NULL;
1123 { /* initialise the tab control */
1124 TC_ITEMHEADER tab;
1125 int i;
1126
1127 hw = GetDlgItem (hwnd, IDC_TAB);
1128 for (i=0; i<npanels; i++) {
1129 tab.mask = TCIF_TEXT;
1130 tab.pszText = names[panelnums[i]];
1131 TabCtrl_InsertItem (hw, i, &tab);
1132 }
1133 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1134 hwnd, panelproc[panelnums[0]]);*/
1135 *page = CreateDialog (hinst, panelids[panelnums[0]],
1136 hwnd, panelproc[panelnums[0]]);
1137 SetWindowLong (*page, GWL_EXSTYLE,
1138 GetWindowLong (*page, GWL_EXSTYLE) |
1139 WS_EX_CONTROLPARENT);
1140 }
1141 SetFocus (*page);
1142 return 0;
1143 case WM_NOTIFY:
1144 if (LOWORD(wParam) == IDC_TAB &&
1145 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1146 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1147 if (*page)
1148 DestroyWindow (*page);
1149 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1150 hwnd, panelproc[panelnums[i]]);*/
1151 *page = CreateDialog (hinst, panelids[panelnums[i]],
1152 hwnd, panelproc[panelnums[i]]);
1153 SetWindowLong (*page, GWL_EXSTYLE,
1154 GetWindowLong (*page, GWL_EXSTYLE) |
1155 WS_EX_CONTROLPARENT);
1156 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1157 return 0;
1158 }
1159 break;
1160 /* case WM_CTLCOLORDLG: */
1161 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1162 case WM_COMMAND:
1163 switch (LOWORD(wParam)) {
1164 case IDOK:
1165 if (*cfg.host)
1166 EndDialog (hwnd, 1);
1167 else
1168 MessageBeep (0);
1169 return 0;
1170 case IDCANCEL:
1171 EndDialog (hwnd, 0);
1172 return 0;
1173 }
1174 return 0;
1175 case WM_CLOSE:
1176 EndDialog (hwnd, 0);
1177 return 0;
1178 }
1179 return 0;
1180 }
1181
1182 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1183 WPARAM wParam, LPARAM lParam) {
1184 #if 0
1185 HWND hw;
1186 int i;
1187 #endif
1188 static HWND page = NULL;
1189
1190 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1191 #if 0
1192 /*
1193 * If the Connection panel is active and the Session List
1194 * box is selected, we treat a press of Open to have an
1195 * implicit press of Load preceding it.
1196 */
1197 hw = GetDlgItem (hwnd, IDC_TAB);
1198 i = TabCtrl_GetCurSel(hw);
1199 if (panelproc[mainp[i]] == ConnectionProc &&
1200 page && implicit_load_ok) {
1201 SendMessage (page, WM_COMMAND,
1202 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1203 }
1204 #endif
1205 }
1206 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1207 EnableWindow(hwnd, 0);
1208 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1209 GetParent(hwnd), AboutProc);
1210 EnableWindow(hwnd, 1);
1211 }
1212 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1213 MAIN_NPANELS, mainp, &page);
1214 }
1215
1216 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1217 WPARAM wParam, LPARAM lParam) {
1218 static HWND page;
1219 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1220 RECONF_NPANELS, reconfp, &page);
1221 }
1222
1223 void get_sesslist(int allocate) {
1224 static char *buffer;
1225 int buflen, bufsize, i, ret;
1226 char otherbuf[2048];
1227 char *p;
1228 HKEY subkey1;
1229
1230 if (allocate) {
1231 if (RegCreateKey(HKEY_CURRENT_USER,
1232 puttystr, &subkey1) != ERROR_SUCCESS)
1233 return;
1234
1235 buflen = bufsize = 0;
1236 buffer = NULL;
1237 i = 0;
1238 do {
1239 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1240 if (ret == ERROR_SUCCESS) {
1241 bufsize = buflen + 2048;
1242 buffer = srealloc(buffer, bufsize);
1243 unmungestr(otherbuf, buffer+buflen);
1244 buflen += strlen(buffer+buflen)+1;
1245 }
1246 } while (ret == ERROR_SUCCESS);
1247 buffer = srealloc(buffer, buflen+1);
1248 buffer[buflen] = '\0';
1249
1250 p = buffer;
1251 nsessions = 1; /* "Default Settings" counts as one */
1252 while (*p) {
1253 if (strcmp(p, "Default Settings"))
1254 nsessions++;
1255 while (*p) p++;
1256 p++;
1257 }
1258
1259 sessions = smalloc(nsessions * sizeof(char *));
1260 sessions[0] = "Default Settings";
1261 p = buffer;
1262 i = 1;
1263 while (*p) {
1264 if (strcmp(p, "Default Settings"))
1265 sessions[i++] = p;
1266 while (*p) p++;
1267 p++;
1268 }
1269 } else {
1270 sfree (buffer);
1271 sfree (sessions);
1272 }
1273 }
1274
1275 int do_config (void) {
1276 int ret;
1277
1278 get_sesslist(TRUE);
1279 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1280 get_sesslist(FALSE);
1281
1282 return ret;
1283 }
1284
1285 int do_reconfig (HWND hwnd) {
1286 Config backup_cfg;
1287 int ret;
1288
1289 backup_cfg = cfg; /* structure copy */
1290 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1291 if (!ret)
1292 cfg = backup_cfg; /* structure copy */
1293 return ret;
1294 }
1295
1296 void do_defaults (char *session) {
1297 if (session)
1298 load_settings (session, TRUE);
1299 else
1300 load_settings ("Default Settings", FALSE);
1301 }
1302
1303 void lognegot (char *string) {
1304 if (nnegots >= negsize) {
1305 negsize += 64;
1306 negots = srealloc (negots, negsize * sizeof(*negots));
1307 }
1308 negots[nnegots] = smalloc(1+strlen(string));
1309 strcpy (negots[nnegots], string);
1310 nnegots++;
1311 if (logbox)
1312 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1313 0, (LPARAM)string);
1314 }
1315
1316 void shownegot (HWND hwnd) {
1317 if (!logbox) {
1318 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1319 hwnd, LogProc);
1320 ShowWindow (logbox, SW_SHOWNORMAL);
1321 }
1322 }
1323
1324 void showabout (HWND hwnd) {
1325 if (!abtbox) {
1326 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1327 hwnd, AboutProc);
1328 ShowWindow (abtbox, SW_SHOWNORMAL);
1329 }
1330 }
1331
1332 void verify_ssh_host_key(char *host, struct RSAKey *key) {
1333 char *keystr, *otherstr, *mungedhost;
1334 int len;
1335 HKEY rkey;
1336
1337 /*
1338 * Format the key into a string.
1339 */
1340 len = rsastr_len(key);
1341 keystr = malloc(len);
1342 if (!keystr)
1343 fatalbox("Out of memory");
1344 rsastr_fmt(keystr, key);
1345
1346 /*
1347 * Now read a saved key in from the registry and see what it
1348 * says.
1349 */
1350 otherstr = malloc(len);
1351 mungedhost = malloc(3*strlen(host)+1);
1352 if (!otherstr || !mungedhost)
1353 fatalbox("Out of memory");
1354
1355 mungestr(host, mungedhost);
1356
1357 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1358 &rkey) != ERROR_SUCCESS) {
1359 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1360 "in the registry. There is thus no way to tell\n"
1361 "if the remote host is what you think it is.\n"
1362 "Connect anyway?", "PuTTY Problem",
1363 MB_ICONWARNING | MB_YESNO) == IDNO)
1364 exit(0);
1365 } else {
1366 DWORD readlen = len;
1367 DWORD type;
1368 int ret;
1369
1370 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1371 &type, otherstr, &readlen);
1372
1373 if (ret == ERROR_MORE_DATA ||
1374 (ret == ERROR_SUCCESS && type == REG_SZ &&
1375 strcmp(otherstr, keystr))) {
1376 if (MessageBox(NULL,
1377 "This host's host key is different from the\n"
1378 "one cached in the registry! Someone may be\n"
1379 "impersonating this host for malicious reasons;\n"
1380 "alternatively, the host key may have changed\n"
1381 "due to sloppy system administration.\n"
1382 "Replace key in registry and connect?",
1383 "PuTTY: Security Warning",
1384 MB_ICONWARNING | MB_YESNO) == IDNO)
1385 exit(0);
1386 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1387 strlen(keystr)+1);
1388 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1389 if (MessageBox(NULL,
1390 "This host's host key is not cached in the\n"
1391 "registry. Do you want to add it to the cache\n"
1392 "and carry on connecting?",
1393 "PuTTY: New Host",
1394 MB_ICONWARNING | MB_YESNO) == IDNO)
1395 exit(0);
1396 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1397 strlen(keystr)+1);
1398 }
1399
1400 RegCloseKey(rkey);
1401 }
1402 }