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