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