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