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