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