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