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