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