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