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