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