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