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