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